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** comep.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** These routines allow applications to manipulate information in the 90** endpoint mapper database. 91** 92*/ 93 94#include <commonp.h> /* Common internals for RPC runtime system */ 95#include <com.h> /* Externals for Common Services component */ 96#include <comp.h> /* Private communications services */ 97#include <dce/ep.h> /* NIDL generated include for ep interface */ 98#include <comtwr.h> /* Tower <=> Tower ref routines */ 99#include <comtwrref.h> /* Tower ref routines */ 100#include <comtwrflr.h> /* Tower floor routines */ 101 102 103/* 104 * Number of compatible towers to be returned from ept_map in one call. 105 */ 106#define MAX_TOWERS 15 107 108/* 109 * Magic cookie to check mgmt_ep inquiry_context. 110 */ 111#define MGMT_EP_C_INQUIRY_CONTEXT 1234 112 113/* 114 * mgmt_ep inquiry context. 115 */ 116 117#define MAX_ENTS 15 118 119typedef struct { 120 unsigned32 usage; 121 ndr_boolean done; 122 rpc_binding_handle_t ep_binding; 123 unsigned32 inquiry_type; 124 idl_uuid_t object; 125 rpc_if_id_t if_id; 126 unsigned32 vers_option; 127 ept_lookup_handle_t entry_handle; 128 unsigned32 num_ents; 129 unsigned32 next_ent; 130 ept_entry_t entries[MAX_ENTS]; 131} mgmt_ep_inq_rep_t, *mgmt_ep_inq_rep_p_t; 132 133INTERNAL void ep_register ( 134 rpc_if_handle_t ifspec, 135 rpc_binding_vector_t *binding_vec, 136 uuid_vector_t *object_uuid_vec, 137 unsigned_char_p_t annotation, 138 boolean32 replace, 139 unsigned32 * /*status*/ 140 ); 141 142INTERNAL void get_ep_binding ( 143 rpc_binding_handle_t input_binding, 144 rpc_binding_handle_t *output_binding, 145 unsigned32 * /*status*/ 146 ); 147 148INTERNAL void tower_to_if_id ( 149 twr_p_t tower, 150 rpc_if_id_t *if_id, 151 unsigned32 * /*status*/ 152 ); 153 154INTERNAL void ep_get_endpoint ( 155 rpc_if_rep_p_t if_r, 156 rpc_binding_rep_p_t binding_r, 157 unsigned32 * /*st*/ 158 ); 159 160INTERNAL idl_void_p_t rpc__ep_mem_alloc ( 161 idl_void_p_t /* context */, 162 idl_size_t /*size*/ 163 ); 164 165INTERNAL void rpc__ep_mem_free ( 166 idl_void_p_t /* context */, 167 dce_pointer_t /*ptr*/ 168 ); 169 170 171/* 172**++ 173** 174** ROUTINE NAME: rpc_ep_register 175** 176** SCOPE: PUBLIC - declared in rpc.idl 177** 178** DESCRIPTION: 179** 180** Adds server address information to the endpoint mapper database. 181** A server routine calls this routine only if the server has dynamically 182** generated endpoints. 183** 184** INPUTS: 185** 186** ifspec Interface specification to register with the 187** endpoint mapper. 188** 189** binding_vec Vector of binding handles over which the server 190** can receive RPCs. 191** 192** object_uuid_vec A vector of object UUIDs offered by the server. 193** The server application constructs this vector. 194** 195** annotation A character string comment applied to each cross- 196** product entry added to the endpoint mapper. 197** 198** INPUTS/OUTPUTS: none 199** 200** OUTPUTS: 201** 202** status The result of the operation. One of: 203** rpc_s_ok 204** rpc_s_no_bindings 205** rpc_s_invalid_binding 206** 207** IMPLICIT INPUTS: none 208** 209** IMPLICIT OUTPUTS: none 210** 211** FUNCTION VALUE: void 212** 213** SIDE EFFECTS: none 214** 215**-- 216**/ 217 218PUBLIC void rpc_ep_register 219( 220 rpc_if_handle_t ifspec, 221 rpc_binding_vector_t *binding_vec, 222 uuid_vector_t *object_uuid_vec, 223 unsigned_char_p_t annotation, 224 unsigned32 *status 225) 226{ 227 ep_register (ifspec, binding_vec, object_uuid_vec, annotation, true, status); 228} 229 230/* 231**++ 232** 233** ROUTINE NAME: rpc_ep_register_no_replace 234** 235** SCOPE: PUBLIC - declared in rpc.idl 236** 237** DESCRIPTION: 238** 239** Like rpc_ep_register, except doesn't replace any existing entries. 240** 241** INPUTS: 242** 243** ifspec Interface specification to register with the 244** endpoint mapper. 245** 246** binding_vec Vector of binding handles over which the server 247** can receive RPCs. 248** 249** object_uuid_vec A vector of object UUIDs offered by the server. 250** The server application constructs this vector. 251** 252** annotation A character string comment applied to each cross- 253** product entry added to the endpoint mapper. 254** 255** INPUTS/OUTPUTS: none 256** 257** OUTPUTS: 258** 259** status The result of the operation. One of: 260** rpc_s_ok 261** rpc_s_no_bindings 262** rpc_s_invalid_binding 263** 264** IMPLICIT INPUTS: none 265** 266** IMPLICIT OUTPUTS: none 267** 268** FUNCTION VALUE: void 269** 270** SIDE EFFECTS: none 271** 272**-- 273**/ 274 275PUBLIC void rpc_ep_register_no_replace 276( 277 rpc_if_handle_t ifspec, 278 rpc_binding_vector_t *binding_vec, 279 uuid_vector_t *object_uuid_vec, 280 unsigned_char_p_t annotation, 281 unsigned32 *status 282) 283{ 284 ep_register (ifspec, binding_vec, object_uuid_vec, annotation, false, status); 285} 286 287/* 288**++ 289** 290** ROUTINE NAME: ep_register 291** 292** SCOPE: INTERNAL 293** 294** DESCRIPTION: 295** 296** Common routine for rpc_ep_register*. 297** 298** INPUTS: 299** 300** ifspec Interface specification to register with the 301** endpoint mapper. 302** 303** binding_vec Vector of binding handles over which the server 304** can receive RPCs. 305** 306** object_uuid_vec A vector of object UUIDs offered by the server. 307** The server application constructs this vector. 308** 309** annotation A character string comment applied to each cross- 310** product entry added to the endpoint mapper. 311** 312** INPUTS/OUTPUTS: none 313** 314** OUTPUTS: 315** 316** status The result of the operation. One of: 317** rpc_s_ok 318** rpc_s_no_interfaces 319** rpc_s_no_bindings 320** rpc_s_invalid_binding 321** 322** IMPLICIT INPUTS: none 323** 324** IMPLICIT OUTPUTS: none 325** 326** FUNCTION VALUE: void 327** 328** SIDE EFFECTS: none 329** 330**-- 331**/ 332 333INTERNAL void ep_register 334( 335 rpc_if_handle_t ifspec, 336 rpc_binding_vector_t *binding_vec, 337 uuid_vector_t *object_uuid_vec, 338 unsigned_char_p_t annotation, 339 boolean32 replace, 340 unsigned32 *status 341) 342{ 343 ept_entry_t *ept_entry; 344 rpc_if_rep_p_t if_rep = (rpc_if_rep_p_t) ifspec; 345 rpc_binding_handle_t ep_binding = NULL; 346 unsigned32 i, j; 347 unsigned32 curr_hand = 0, curr_tower = 0, curr_obj = 0; 348 unsigned32 st; 349 rpc_tower_ref_vector_p_t tower_vec; 350 351 CODING_ERROR (status); 352 RPC_VERIFY_INIT (); 353 354 if (ifspec == NULL) 355 { 356 *status = rpc_s_no_interfaces; 357 return; 358 } 359 360 if (binding_vec == NULL || binding_vec->count == 0) 361 { 362 *status = rpc_s_no_bindings; 363 return; 364 } 365 366#ifndef __hpux__ 367 /* 368 * First attempt to contact the local endpoint mapper with ncalrpc. 369 * This should work even if the network has not yet come up 370 */ 371 rpc_binding_from_string_binding( 372 (unsigned_char_t*) "ncalrpc:[epmapper]", 373 &ep_binding, 374 status); 375 376 if (*status == rpc_s_ok) 377 { 378 if (!rpc_mgmt_is_server_listening(ep_binding, status)) 379 { 380 rpc_binding_free(&ep_binding, status); 381 ep_binding = NULL; 382 } 383 } 384#endif 385 386 if (!ep_binding) 387 { 388 /* 389 * Spin through the binding vector array looking for a non-NULL pointer 390 * to a binding handle. If one is found set curr_hand to its offset in 391 * the binding vector. 392 * Also check for a binding handle with no endpoint; if one is found 393 * return an error. 394 */ 395 396 curr_hand = binding_vec->count; 397 for (i = 0; i < binding_vec->count; i++) 398 { 399 if (binding_vec->binding_h[i] != NULL) 400 { 401 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_vec->binding_h[i]; 402 if (binding_rep->addr_has_endpoint == false) 403 { 404 *status = rpc_s_invalid_binding; 405 return; 406 } 407 408#ifdef __hpux__ 409 if (binding_rep->rpc_addr && binding_rep->rpc_addr->sa.family == RPC_C_NAF_ID_IP) 410 { 411 struct sockaddr_in* addr = (struct sockaddr_in*) &binding_rep->rpc_addr->sa; 412 unsigned char* addr_bytes = (unsigned char*) &addr->sin_addr.s_addr; 413 414 /* Don't attempt to connect on the loopback interface on HP-UX 415 because the ep mapper incorrectly rejects attempts to register 416 mappings through it */ 417 if (addr_bytes[0] == 127) 418 { 419 continue; 420 } 421 } 422 423 if (binding_rep->rpc_addr && binding_rep->rpc_addr->rpc_protseq_id == rpc_c_protseq_id_ncalrpc) 424 { 425 /* Don't attempt to connect over ncalrpc on HP-UX because its native DCE 426 implementation does not understand it */ 427 continue; 428 } 429#endif 430 431 curr_hand = i; 432 break; 433 } 434 } 435 436 /* 437 * If all the handles were NULL'd out, return an error. 438 */ 439 440 if (curr_hand >= binding_vec->count) 441 { 442 *status = rpc_s_no_bindings; 443 return; 444 } 445 446 /* 447 * Otherwise, use the a valid handle to converse with the EP mapper. 448 */ 449 450 get_ep_binding(binding_vec->binding_h[curr_hand], &ep_binding, status); 451 if (*status != rpc_s_ok) 452 return; 453 } 454 455 /* 456 * Allocate the EP entry structure to avoid taking up stack space. 457 */ 458 459 RPC_MEM_ALLOC(ept_entry, ept_entry_t *, sizeof *ept_entry, 460 RPC_C_MEM_EPT_ENTRY, RPC_C_MEM_NOWAIT); 461 462 rpc__strncpy(ept_entry->annotation, annotation, ept_max_annotation_size - 1); 463 464 for (curr_hand = 0; curr_hand < binding_vec->count; curr_hand++) 465 { 466 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_vec->binding_h[curr_hand]; 467 /* 468 * Skip over NULL entries. 469 */ 470 471 if (binding_rep == NULL) 472 { 473 continue; 474 } 475 476 if (binding_rep->rpc_addr && rpc_g_protseq_id[binding_rep->rpc_addr->rpc_protseq_id].uses_ep_mapper == 0) 477 { 478 /* Skip over protocol sequences that do not require the endpoint mapper */ 479 continue; 480 } 481 482 /* 483 * Convert the binding handle to tower_ref vector. 484 */ 485 486 rpc__tower_ref_vec_from_binding(if_rep, binding_vec->binding_h[curr_hand], 487 &tower_vec, status); 488 if (*status != rpc_s_ok) 489 break; 490 491 for (curr_tower = 0; curr_tower < tower_vec->count; curr_tower++) 492 { 493 rpc__tower_from_tower_ref(tower_vec->tower[curr_tower], &ept_entry->tower, status); 494 if (*status != rpc_s_ok) 495 break; 496 497 if (object_uuid_vec == NULL || object_uuid_vec->count == 0) 498 { 499 ept_entry->object = uuid_g_nil_uuid; 500 (*ept_v3_0_c_epv.ept_insert) 501 (ep_binding, 1L, ept_entry, replace, status); 502 if (*status == rpc_s_call_cancelled) 503 dcethread_interrupt_throw(dcethread_self()); 504 } 505 else 506 { 507 for (curr_obj = 0; curr_obj < object_uuid_vec->count; curr_obj++) 508 { 509 ept_entry->object = *object_uuid_vec->uuid[curr_obj]; 510 (*ept_v3_0_c_epv.ept_insert) 511 (ep_binding, 1L, ept_entry, replace, status); 512 if (*status == rpc_s_call_cancelled) 513 dcethread_interrupt_throw(dcethread_self()); 514 if (*status != rpc_s_ok) 515 break; 516 } 517 } 518 519 rpc__tower_free(&ept_entry->tower, &st); 520 521 if (*status != rpc_s_ok) 522 break; 523 } 524 525 rpc__tower_ref_vec_free(&tower_vec, &st); 526 527 if (*status != rpc_s_ok) 528 break; 529 } 530 531 rpc_binding_free(&ep_binding, &st); 532 RPC_MEM_FREE(ept_entry, RPC_C_MEM_EPT_ENTRY); 533 534 /* 535 * Handle any error conditions. Try to unregister anything that was 536 * successfully registered. Since we were trying to register the 537 * cross product of two vectors we need to separate recovery into 538 * 1) binding handles for which all objects were successfully registered 539 * and 2) binding handles for which some of the objects were successfully 540 * registered. 541 * Punt on the fact that multiple towers can be derived from each binding 542 * handle - all towers associated with a binding handle will be unregistered 543 * by rpc_ep_unregister. 544 */ 545 546 if ((*status != rpc_s_ok) && (*status != rpc_s_comm_failure) && 547 (curr_hand > 0 || curr_tower > 0 || curr_obj > 0)) 548 { 549 rpc_binding_vector_p_t bvp; 550 uuid_vector_p_t ovp = NULL; 551 unsigned32 bv_size, ov_size; 552 553 /* 554 * First alloc a binding vector large enough to hold the number 555 * of handles for which all objects were successfully registered. 556 * (with a minimum size of 1 handle so that we can use it for the 557 * partially successful handle also). 558 */ 559 560 bv_size = sizeof(rpc_binding_vector_t) + (sizeof(handle_t) * curr_hand); 561 RPC_MEM_ALLOC(bvp, rpc_binding_vector_p_t, bv_size, 562 RPC_C_MEM_BINDING_VEC, RPC_C_MEM_WAITOK); 563 if (bvp == NULL) 564 { 565 *status = rpc_s_no_memory; 566 return; 567 } 568 569 /* 570 * If there were any handles that were fully registered, 571 * unregister them now. 572 */ 573 574 if (curr_hand > 0) 575 { 576 bvp->count = curr_hand; 577 for (j = 0; j < bvp->count; j++) 578 bvp->binding_h[j] = binding_vec->binding_h[j]; 579 580 rpc_ep_unregister(ifspec, bvp, object_uuid_vec, &st); 581 } 582 583 /* 584 * If we got part way through registering the towers associated 585 * with a binding handle for an object, behave as if we registered 586 * all the towers associated with the binding handle and the object, 587 * ie. increment the curr_obj. 588 */ 589 if (curr_tower > 0) curr_obj++; 590 591 /* 592 * If we got part way through registering the object vector for 593 * a particular handle, then we'll need to create a smaller copy 594 * of the object vector for unregistering only those objects that 595 * were actually registered (with that particular handle). 596 */ 597 598 if (curr_obj > 0) 599 { 600 /* 601 * First create the partial object vector. 602 */ 603 604 ov_size = sizeof(uuid_vector_t) + (sizeof(idl_uuid_t) * (curr_obj - 1)); 605 RPC_MEM_ALLOC(ovp, uuid_vector_p_t, ov_size, 606 RPC_C_MEM_UUID_VECTOR, RPC_C_MEM_WAITOK); 607 if (ovp == NULL) 608 { 609 *status = rpc_s_no_memory; 610 RPC_MEM_FREE(bvp, RPC_C_MEM_UUID_VECTOR); 611 return; 612 } 613 614 ovp->count = curr_obj; 615 assert(object_uuid_vec != NULL); 616 for (j = 0; j < curr_obj; j++) 617 ovp->uuid[j] = object_uuid_vec->uuid[j]; 618 619 /* 620 * Next, make a binding vector which contains only this 621 * particular handle. 622 */ 623 624 bvp->count = 1; 625 bvp->binding_h[0] = binding_vec->binding_h[curr_hand]; 626 627 rpc_ep_unregister(ifspec, bvp, ovp, &st); 628 629 RPC_MEM_FREE(ovp, RPC_C_MEM_UUID_VECTOR); 630 } 631 632 RPC_MEM_FREE(bvp, RPC_C_MEM_BINDING_VEC); 633 } 634} 635 636/* 637**++ 638** 639** ROUTINE NAME: rpc_ep_unregister 640** 641** SCOPE: PUBLIC - declared in rpc.idl 642** 643** DESCRIPTION: 644** 645** Removes server address information from the endpoint mapper database. 646** A server calls this routine only if the server has previously 647** registered dynamically allocated endpoints. 648** 649** INPUTS: 650** 651** ifspec Interface specification to unregister with the 652** endpoint mapper. 653** 654** binding_vec Vector of binding handles to unregister 655** 656** object_uuid_vec A vector of object UUIDs to unregister 657** 658** INPUTS/OUTPUTS: none 659** 660** OUTPUTS: 661** 662** status The result of the operation. One of: 663** rpc_s_ok 664** rpc_s_no_interfaces 665** rpc_s_no_bindings 666** rpc_s_invalid_binding 667** 668** IMPLICIT INPUTS: none 669** 670** IMPLICIT OUTPUTS: none 671** 672** FUNCTION VALUE: void 673** 674** SIDE EFFECTS: none 675** 676**-- 677**/ 678 679PUBLIC void rpc_ep_unregister 680( 681 rpc_if_handle_t ifspec, 682 rpc_binding_vector_t *binding_vec, 683 uuid_vector_t *object_uuid_vec, 684 unsigned32 *status 685) 686{ 687 ept_entry_t *ept_entry; 688 rpc_if_rep_p_t if_rep = (rpc_if_rep_p_t) ifspec; 689 rpc_binding_handle_t ep_binding = NULL; 690 unsigned32 i, j, k, st; 691 rpc_tower_ref_vector_p_t tower_vec; 692 unsigned32 curr_hand; 693 unsigned32 lstatus; 694 695 CODING_ERROR (status); 696 RPC_VERIFY_INIT (); 697 698 if (ifspec == NULL) 699 { 700 *status = rpc_s_no_interfaces; 701 return; 702 } 703 704 if (binding_vec == NULL || binding_vec->count == 0) 705 { 706 *status = rpc_s_no_bindings; 707 return; 708 } 709 710#ifndef __hpux__ 711 /* 712 * First attempt to contact the local endpoint mapper with ncalrpc. 713 * This should work even if the network has not yet come up 714 */ 715 rpc_binding_from_string_binding( 716 (unsigned_char_t*) "ncalrpc:[epmapper]", 717 &ep_binding, 718 status); 719 720 if (*status == rpc_s_ok) 721 { 722 if (!rpc_mgmt_is_server_listening(ep_binding, status)) 723 { 724 rpc_binding_free(&ep_binding, status); 725 ep_binding = NULL; 726 } 727 } 728#endif 729 730 if (!ep_binding) 731 { 732 /* 733 * Spin through the binding vector array looking for a non-NULL pointer 734 * to a binding handle. If one is found set curr_hand to its offset in 735 * the binding vector. 736 * Also check for a binding handle with no endpoint; if one is found 737 * return an error. 738 */ 739 740 curr_hand = binding_vec->count; 741 for (i = 0; i < binding_vec->count; i++) 742 { 743 if (binding_vec->binding_h[i] != NULL) 744 { 745 if (((rpc_binding_rep_p_t) binding_vec->binding_h[i]) 746 ->addr_has_endpoint == false) 747 { 748 *status = rpc_s_invalid_binding; 749 return; 750 } 751 752 curr_hand = i; 753 } 754 } 755 756 /* 757 * If all the handles were NULL'd out, return an error. 758 */ 759 760 if (curr_hand >= binding_vec->count) 761 { 762 *status = rpc_s_no_bindings; 763 return; 764 } 765 766 /* 767 * Otherwise, use the a valid handle to converse with the EP mapper. 768 */ 769 770 get_ep_binding(binding_vec->binding_h[curr_hand], &ep_binding, status); 771 if (*status != rpc_s_ok) 772 return; 773 } 774 775 /* 776 * Allocate the EP entry structure to avoid taking up stack space. 777 */ 778 779 RPC_MEM_ALLOC(ept_entry, ept_entry_t *, sizeof *ept_entry, 780 RPC_C_MEM_EPT_ENTRY, RPC_C_MEM_NOWAIT); 781 782 ept_entry->annotation[0] = 0; 783 784 /* 785 * We will try to unregister the endpoints as much as possible and 786 * report the first error status we see (if that happens). 787 * 788 * Note: There is no particular reason why we report the first 789 * error. (It can be the last one or middle.) The better 790 * implementation is to make the endpoint mapper (rpcd) interface 791 * accept a vector of endpoints and return a vector of status codes 792 * for ept_insert() and ept_delete(). It may also improve the 793 * performance. 794 */ 795 796 lstatus = rpc_s_ok; 797 798 for (i = 0; i < binding_vec->count; i++) 799 { 800 /* 801 * Skip over NULL entries. 802 */ 803 804 if (binding_vec->binding_h[i] == NULL) 805 continue; 806 807 if (binding_vec->binding_h[i]->rpc_addr && 808 rpc_g_protseq_id[binding_vec->binding_h[i]->rpc_addr->rpc_protseq_id].uses_ep_mapper == 0) 809 { 810 /* Skip over protocol sequences that do not require the endpoint mapper */ 811 continue; 812 } 813 814 /* 815 * Convert the binding handle to tower_ref vector 816 */ 817 818 rpc__tower_ref_vec_from_binding(if_rep, binding_vec->binding_h[i], 819 &tower_vec, &st); 820 if (st != rpc_s_ok) 821 { 822 if (lstatus == rpc_s_ok) 823 lstatus = st; 824 825 continue; 826 } 827 828 for (j = 0; j < tower_vec->count; j++) 829 { 830 rpc__tower_from_tower_ref(tower_vec->tower[j], &ept_entry->tower, &st); 831 if (st != rpc_s_ok) 832 { 833 if (lstatus == rpc_s_ok) 834 lstatus = st; 835 836 continue; 837 } 838 839 if (object_uuid_vec == NULL || object_uuid_vec->count == 0) 840 { 841 ept_entry->object = uuid_g_nil_uuid; 842 (*ept_v3_0_c_epv.ept_delete)(ep_binding, 1L, ept_entry, &st); 843 if (st == rpc_s_call_cancelled) 844 dcethread_interrupt_throw(dcethread_self()); 845 } 846 else 847 { 848 for (k = 0; k < object_uuid_vec->count; k++) 849 { 850 ept_entry->object = *object_uuid_vec->uuid[k]; 851 (*ept_v3_0_c_epv.ept_delete)(ep_binding, 1L, ept_entry, &st); 852 if (st != rpc_s_ok) 853 { 854 if (*status == rpc_s_call_cancelled) 855 dcethread_interrupt_throw(dcethread_self()); 856 if (lstatus == rpc_s_ok) 857 lstatus = st; 858 859 continue; 860 } 861 } 862 } 863 864 if (st != rpc_s_ok) 865 { 866 if (lstatus == rpc_s_ok) 867 lstatus = st; 868 } 869 870 rpc__tower_free(&ept_entry->tower, &st); 871 } 872 873 rpc__tower_ref_vec_free(&tower_vec, &st); 874 } 875 876 *status = lstatus; 877 rpc_binding_free(&ep_binding, &st); 878 RPC_MEM_FREE(ept_entry, RPC_C_MEM_EPT_ENTRY); 879} 880 881/* 882**++ 883** 884** ROUTINE NAME: rpc_mgmt_ep_elt_inq_begin 885** 886** SCOPE: PUBLIC - declared in rpc.idl 887** 888** DESCRIPTION: 889** 890** Creates an inquiry context for viewing the elements in a local or 891** remote endpoint map database. 892** 893** INPUTS: 894** 895** input_binding 896** 897** inquiry_type 898** 899** if_id 900** 901** vers_option 902** 903** object_uuid 904** 905** 906** INPUTS/OUTPUTS: none 907** 908** OUTPUTS: 909** 910** inquiry_context 911** 912** status The result of the operation. 913** 914** IMPLICIT INPUTS: none 915** 916** IMPLICIT OUTPUTS: none 917** 918** FUNCTION VALUE: void 919** 920** SIDE EFFECTS: none 921** 922**-- 923**/ 924 925PUBLIC void rpc_mgmt_ep_elt_inq_begin 926( 927 rpc_binding_handle_t input_binding, 928 unsigned32 inquiry_type, 929 rpc_if_id_p_t if_id, 930 unsigned32 vers_option, 931 uuid_p_t object_uuid, 932 rpc_ep_inq_handle_t *inquiry_context, 933 unsigned32 *status 934) 935{ 936 mgmt_ep_inq_rep_t *chp; 937 rpc_binding_handle_t ep_binding; 938 idl_uuid_t UUID_NIL; 939 unsigned32 tmp_st; 940 941 CODING_ERROR (status); 942 RPC_VERIFY_INIT (); 943 944 if (inquiry_context == NULL) 945 { 946 *status = rpc_s_invalid_inquiry_context; 947 return; 948 } 949 950 *inquiry_context = NULL; 951 952 get_ep_binding(input_binding, &ep_binding, status); 953 if (*status != rpc_s_ok) 954 return; 955 956 RPC_MEM_ALLOC ( 957 chp, 958 mgmt_ep_inq_rep_p_t, 959 sizeof (mgmt_ep_inq_rep_t), 960 RPC_C_MEM_INQ_REP, 961 RPC_C_MEM_WAITOK); 962 963 chp->usage = MGMT_EP_C_INQUIRY_CONTEXT; 964 chp->done = false; 965 chp->ep_binding = ep_binding; 966 chp->inquiry_type = inquiry_type; 967 chp->vers_option = vers_option; 968 chp->entry_handle = NULL; 969 chp->num_ents = 0; 970 chp->next_ent = 0; 971 972 /* 973 * Fill context's object and interface specs. If object isn't being 974 * matched, use nil_uuid. If interface isn't being matched, use 975 * nil_uuid and versions = 0. 976 */ 977 978 uuid_create_nil(&UUID_NIL, &tmp_st); 979 980 switch ((int)inquiry_type) 981 { 982 case rpc_c_ep_all_elts: 983 chp->object = UUID_NIL; 984 chp->if_id.uuid = UUID_NIL; 985 chp->if_id.vers_major = 0; 986 chp->if_id.vers_minor = 0; 987 break; 988 989 case rpc_c_ep_match_by_if: 990 chp->object = UUID_NIL; 991 chp->if_id = *if_id; 992 break; 993 994 case rpc_c_ep_match_by_obj: 995 chp->object = *object_uuid; 996 chp->if_id.uuid = UUID_NIL; 997 chp->if_id.vers_major = 0; 998 chp->if_id.vers_minor = 0; 999 break; 1000 1001 case rpc_c_ep_match_by_both: 1002 chp->object = *object_uuid; 1003 chp->if_id = *if_id; 1004 break; 1005 1006 default: 1007 *status = rpc_s_invalid_inquiry_type; 1008 rpc_binding_free(&ep_binding, &tmp_st); 1009 RPC_MEM_FREE(chp, RPC_C_MEM_INQ_REP); 1010 return; 1011 } 1012 1013 if ((inquiry_type == rpc_c_ep_match_by_if) || (inquiry_type == rpc_c_ep_match_by_both)) 1014 { 1015 switch((int)vers_option) 1016 { 1017 case rpc_c_vers_all: 1018 case rpc_c_vers_compatible: 1019 case rpc_c_vers_exact: 1020 case rpc_c_vers_major_only: 1021 case rpc_c_vers_upto: 1022 break; 1023 1024 default: 1025 *status = rpc_s_invalid_vers_option; 1026 rpc_binding_free(&ep_binding, &tmp_st); 1027 RPC_MEM_FREE(chp, RPC_C_MEM_INQ_REP); 1028 return; 1029 } 1030 } 1031 1032 *inquiry_context = (rpc_ep_inq_handle_t) chp; 1033 1034 *status = rpc_s_ok; 1035} 1036 1037 1038/* 1039**++ 1040** 1041** ROUTINE NAME: rpc_mgmt_ep_elt_inq_next 1042** 1043** SCOPE: PUBLIC - declared in rpc.idl 1044** 1045** DESCRIPTION: 1046** 1047** Returns one element at a time from a local or remote endpoint map 1048** database. 1049** 1050** INPUTS: 1051** 1052** inquiry_context 1053** 1054** INPUTS/OUTPUTS: none 1055** 1056** OUTPUTS: 1057** 1058** if_id 1059** 1060** binding 1061** 1062** object_uuid 1063** 1064** annotation 1065** 1066** status The result of the operation. 1067** 1068** IMPLICIT INPUTS: none 1069** 1070** IMPLICIT OUTPUTS: none 1071** 1072** FUNCTION VALUE: void 1073** 1074** SIDE EFFECTS: none 1075** 1076**-- 1077**/ 1078PUBLIC void rpc_mgmt_ep_elt_inq_next 1079( 1080 rpc_ep_inq_handle_t inquiry_context, 1081 rpc_if_id_t *if_id, 1082 rpc_binding_handle_t *binding, 1083 idl_uuid_t *object_uuid, 1084 unsigned_char_p_t *annotation, 1085 unsigned32 *status 1086) 1087{ 1088 mgmt_ep_inq_rep_t *chp; 1089 ept_entry_t *entp; 1090 unsigned32 asize; 1091 unsigned32 i; 1092 boolean32 supported_tower = false; 1093 rpc_ss_p_alloc_t old_allocate; 1094 rpc_ss_p_alloc_t tmp_allocate; 1095 rpc_ss_p_free_t old_free; 1096 rpc_ss_p_free_t tmp_free; 1097 1098 CODING_ERROR (status); 1099 RPC_VERIFY_INIT (); 1100 1101 if (inquiry_context == NULL) 1102 { 1103 *status = rpc_s_invalid_inquiry_context; 1104 return; 1105 } 1106 1107 chp = (mgmt_ep_inq_rep_t *) inquiry_context; 1108 1109 if (chp->usage != MGMT_EP_C_INQUIRY_CONTEXT) 1110 { 1111 *status = rpc_s_invalid_inquiry_context; 1112 return; 1113 } 1114 1115 if (if_id == NULL) 1116 { 1117 *status = rpc_s_invalid_arg; 1118 return; 1119 } 1120 1121 /* 1122 * Continue processing towers until we find one with a protseq 1123 * supported by this runtime. 1124 */ 1125 while (!supported_tower) 1126 { 1127 /* 1128 * Check the done flag in the loop just in case the last 1129 * tower isn't supported. We don't want to go and start 1130 * reading towers from the beginning again. 1131 */ 1132 if (chp->done) 1133 { 1134 *status = rpc_s_no_more_elements; 1135 return; 1136 } 1137 1138 if (chp->num_ents == 0) 1139 { 1140 /* 1141 * Force the stub to use a particular form of memory 1142 * allocation. 1143 */ 1144 rpc_ss_swap_client_alloc_free ( 1145 rpc__ep_mem_alloc, rpc__ep_mem_free, 1146 &old_allocate, &old_free); 1147 1148 /* 1149 * No entries stashed away so read some from ept database 1150 */ 1151 (*ept_v3_0_c_epv.ept_lookup)(chp->ep_binding, 1152 chp->inquiry_type, &chp->object, &chp->if_id, chp->vers_option, 1153 &chp->entry_handle, MAX_ENTS, &chp->num_ents, chp->entries, 1154 status); 1155 1156 /* 1157 * Restore the memory allocation scheme in effect before 1158 * we got here. 1159 */ 1160 rpc_ss_swap_client_alloc_free ( 1161 old_allocate, old_free, 1162 &tmp_allocate, &tmp_free); 1163 1164 if (*status != rpc_s_ok) 1165 { 1166 if (*status == ept_s_not_registered) 1167 *status = rpc_s_no_more_elements; 1168 if (*status == rpc_s_call_cancelled) 1169 dcethread_interrupt_throw(dcethread_self()); 1170 return; 1171 } 1172 chp->next_ent = 0; 1173 } 1174 1175 entp = &(chp->entries[chp->next_ent]); 1176 1177 if (binding != NULL) 1178 { 1179 rpc_tower_to_binding(entp->tower->tower_octet_string, binding, 1180 status); 1181 1182 /* 1183 * If the conversion was ok, we have a supported tower. 1184 * If the tower is of an unsupported protseq, we filter it out. 1185 * Any other status is a problem, so return. 1186 */ 1187 if (*status == rpc_s_ok) 1188 { 1189 supported_tower = true; 1190 } 1191 else 1192 { 1193 if (*status != rpc_s_protseq_not_supported) 1194 { 1195 return; 1196 } 1197 } 1198 } 1199 1200 /* 1201 * The caller doesn't want the binding, so consider the tower supported 1202 * to return the other fields. 1203 */ 1204 else 1205 { 1206 supported_tower = true; 1207 } 1208 1209 if (supported_tower) 1210 { 1211 tower_to_if_id(entp->tower, if_id, status); 1212 if (*status != rpc_s_ok) 1213 return; 1214 1215 if (object_uuid != NULL) 1216 *object_uuid = entp->object; 1217 1218 if (annotation != NULL) 1219 { 1220 asize = (unsigned32)strlen((char *) entp->annotation) + 1; 1221 1222 RPC_MEM_ALLOC ( 1223 *annotation, 1224 unsigned_char_p_t, 1225 asize, 1226 RPC_C_MEM_STRING, 1227 RPC_C_MEM_WAITOK); 1228 1229 rpc__strncpy(*annotation, entp->annotation, (asize-1)); 1230 } 1231 } 1232 1233 chp->next_ent++; 1234 1235 if (chp->next_ent >= chp->num_ents) 1236 { 1237 /* 1238 * Have returned all entries that are stashed away for this 1239 * context to the caller. 1240 * Free the towers. 1241 */ 1242 for (i = 0, entp = &(chp->entries[0]); 1243 i < chp->num_ents; 1244 i++, entp++) 1245 { 1246 rpc__ep_mem_free (NULL, (dce_pointer_t) entp->tower); 1247 } 1248 1249 chp->num_ents = 0; 1250 chp->next_ent = 0; 1251 1252 /* 1253 * If entry handle is NULL, all matching entries have been read 1254 * so mark context as done. 1255 */ 1256 if (chp->entry_handle == NULL) 1257 chp->done = true; 1258 } 1259 } 1260 1261 *status = rpc_s_ok; 1262} 1263 1264/* 1265**++ 1266** 1267** ROUTINE NAME: rpc_mgmt_ep_elt_inq_done 1268** 1269** SCOPE: PUBLIC - declared in rpc.idl 1270** 1271** DESCRIPTION: 1272** 1273** Deletes the inquiry context for viewing the elements in a local or 1274** remote endpoint map database. 1275** 1276** INPUTS: none 1277** 1278** INPUTS/OUTPUTS: 1279** 1280** inquiry_context 1281** 1282** OUTPUTS: 1283** 1284** status The result of the operation. 1285** 1286** IMPLICIT INPUTS: none 1287** 1288** IMPLICIT OUTPUTS: none 1289** 1290** FUNCTION VALUE: void 1291** 1292** SIDE EFFECTS: none 1293** 1294**-- 1295**/ 1296 1297PUBLIC void rpc_mgmt_ep_elt_inq_done 1298( 1299 rpc_ep_inq_handle_t *inquiry_context, 1300 unsigned32 *status 1301) 1302{ 1303 mgmt_ep_inq_rep_t *chp; 1304 ept_entry_t *entp; 1305 unsigned32 i; 1306 1307 CODING_ERROR (status); 1308 RPC_VERIFY_INIT (); 1309 1310 if ((inquiry_context == NULL) || (*inquiry_context == NULL)) 1311 { 1312 *status = rpc_s_invalid_inquiry_context; 1313 return; 1314 } 1315 1316 chp = (mgmt_ep_inq_rep_t *) (*inquiry_context); 1317 1318 if (chp->usage != MGMT_EP_C_INQUIRY_CONTEXT) 1319 { 1320 *status = rpc_s_invalid_inquiry_context; 1321 return; 1322 } 1323 1324 if (chp->entry_handle != NULL) 1325 (*ept_v3_0_c_epv.ept_lookup_handle_free)(chp->ep_binding, &chp->entry_handle, status); 1326 if (*status == rpc_s_call_cancelled) 1327 dcethread_interrupt_throw(dcethread_self()); 1328 1329 rpc_binding_free(&chp->ep_binding, status); 1330 1331 for (i = 0, entp = &(chp->entries[0]); i < chp->num_ents; i++, entp++) 1332 rpc__ep_mem_free (NULL, (dce_pointer_t) entp->tower); 1333 1334 RPC_MEM_FREE(chp, RPC_C_MEM_INQ_REP); 1335 1336 *inquiry_context = NULL; 1337 1338 *status = rpc_s_ok; 1339} 1340 1341/* 1342**++ 1343** 1344** ROUTINE NAME: rpc_mgmt_ep_unregister 1345** 1346** SCOPE: PUBLIC - declared in rpc.idl 1347** 1348** DESCRIPTION: 1349** 1350** Removes server address information from an endpoint map database. 1351** 1352** INPUTS: none 1353** 1354** INPUTS/OUTPUTS: 1355** 1356** input_binding 1357** 1358** if_id 1359** 1360** object_uuid 1361** 1362** OUTPUTS: 1363** 1364** status The result of the operation. 1365** 1366** IMPLICIT INPUTS: none 1367** 1368** IMPLICIT OUTPUTS: none 1369** 1370** FUNCTION VALUE: void 1371** 1372** SIDE EFFECTS: none 1373** 1374**-- 1375**/ 1376 1377PUBLIC void rpc_mgmt_ep_unregister 1378( 1379 rpc_binding_handle_t input_binding, 1380 rpc_if_id_p_t if_id, 1381 rpc_binding_handle_t binding, 1382 uuid_p_t object_uuid, 1383 unsigned32 *status 1384) 1385{ 1386 rpc_binding_handle_t ep_binding; 1387 rpc_tower_ref_vector_p_t tower_vec; 1388 twr_p_t tower; 1389 boolean32 object_speced; 1390 idl_uuid_t UUID_NIL; 1391 idl_uuid_t *objp; 1392 error_status_t tmp_st; 1393 rpc_if_rep_t ifspec; 1394 1395 static rpc_syntax_id_t ndr_syntax_id = { 1396 {0x8a885d04UL, 0x1ceb, 0x11c9, 0x9f, 0xe8, {0x8, 0x0, 0x2b, 0x10, 0x48, 0x60}}, 1397 2 1398 }; 1399 static rpc_if_rep_t ifspec_template = { 1400 1, /* ifspec rep version */ 1401 4, /* op count */ 1402 4, /* if version */ 1403 {0, 0, 0, 0, 0, {0}}, /* uuid */ 1404 2, /* stub/rt if version */ 1405 {0, NULL}, /* endpoint vector */ 1406 {1, &ndr_syntax_id}, /* syntax vector */ 1407 NULL, /* server_epv */ 1408 NULL /* manager epv */ 1409 }; 1410 1411 if (if_id == NULL) 1412 { 1413 *status = rpc_s_no_interfaces; 1414 return; 1415 } 1416 1417 if (binding == NULL) 1418 { 1419 *status = rpc_s_invalid_binding; 1420 return; 1421 } 1422 1423 /* 1424 * Get handle to local or remote endpoint mapper 1425 */ 1426 get_ep_binding(input_binding, &ep_binding, status); 1427 if (*status != rpc_s_ok) 1428 return; 1429 1430 /* 1431 * Make up an ifspec from the template 1432 */ 1433 ifspec = ifspec_template; 1434 ifspec.id = if_id->uuid; 1435 ifspec.vers = if_id->vers_minor << 16 | if_id->vers_major; 1436 1437 /* 1438 * Convert the binding handle to tower_ref vector and then to a tower 1439 */ 1440 1441 rpc__tower_ref_vec_from_binding(&ifspec, binding, &tower_vec, status); 1442 if (*status != rpc_s_ok) 1443 { 1444 rpc_binding_free(&ep_binding, &tmp_st); 1445 return; 1446 } 1447 1448 rpc__tower_from_tower_ref(tower_vec->tower[0], &tower, status); 1449 if (*status != rpc_s_ok) 1450 { 1451 rpc_binding_free(&ep_binding, &tmp_st); 1452 rpc__tower_ref_vec_free(&tower_vec, &tmp_st); 1453 return; 1454 } 1455 1456 if (object_uuid == NULL) 1457 { 1458 object_speced = false; 1459 uuid_create_nil(&UUID_NIL, &tmp_st); 1460 objp = &UUID_NIL; 1461 } 1462 else 1463 { 1464 object_speced = true; 1465 objp = object_uuid; 1466 } 1467 1468 (*ept_v3_0_c_epv.ept_mgmt_delete) 1469 (ep_binding, object_speced, objp, tower, status); 1470 1471 if (*status == rpc_s_call_cancelled) 1472 dcethread_interrupt_throw(dcethread_self()); 1473 1474 rpc__tower_free(&tower, &tmp_st); 1475 rpc__tower_ref_vec_free(&tower_vec, &tmp_st); 1476 rpc_binding_free(&ep_binding, &tmp_st); 1477} 1478 1479 1480/* 1481**++ 1482** 1483** ROUTINE NAME: get_ep_binding 1484** 1485** SCOPE: INTERNAL 1486** 1487** DESCRIPTION: 1488** 1489** Return a binding to an endpoint mapper. 1490** 1491** INPUTS: 1492** 1493** input_binding Binding from which we should derive a binding on the 1494** endpoint mapper. Can be NULL to mean the endpoint 1495** mapper on the local host. 1496** 1497** INPUTS/OUTPUTS: none 1498** 1499** OUTPUTS: 1500** 1501** output_binding Binding on the endpoint mapper. 1502** 1503** status The result of the operation. 1504** 1505** IMPLICIT INPUTS: none 1506** 1507** IMPLICIT OUTPUTS: none 1508** 1509** FUNCTION VALUE: void 1510** 1511** SIDE EFFECTS: none 1512** 1513**-- 1514**/ 1515 1516INTERNAL void get_ep_binding 1517( 1518 rpc_binding_handle_t input_binding, 1519 rpc_binding_handle_t *output_binding, 1520 unsigned32 *status 1521) 1522{ 1523 rpc_protseq_vector_t *protseq_vector; 1524 unsigned_char_t protseq_str[64]; 1525 size_t slen; 1526 unsigned32 i; 1527 unsigned32 tmp_st; 1528 1529 /* Workaround due to not having Named Pipe client support yet. */ 1530 if (input_binding != NULL && 1531 input_binding->rpc_addr != NULL && 1532 input_binding->rpc_addr->rpc_protseq_id == rpc_c_protseq_id_ncacn_np) 1533 { 1534 input_binding = NULL; 1535 } 1536 1537 if (input_binding == NULL) 1538 { 1539 /* 1540 * No binding specified. Try to bind to the local rpcd using 1541 * one of the host's supported protseqs. 1542 */ 1543 rpc_network_inq_protseqs(&protseq_vector, status); 1544 if (*status != rpc_s_ok) 1545 return; 1546 1547 for (i = 0; i < protseq_vector->count; i++) 1548 { 1549 slen = strlen((char *) protseq_vector->protseq[i]); 1550 if ((slen + 2) > sizeof(protseq_str)) 1551 continue; 1552 1553 rpc__strncpy(protseq_str, protseq_vector->protseq[i], slen); 1554 rpc__strncpy(&protseq_str[slen], (unsigned_char_t *) ":", 1); 1555 1556 rpc_binding_from_string_binding(protseq_str, output_binding, status); 1557 if (*status == rpc_s_ok) 1558 break; 1559 } 1560 1561 if (i >= protseq_vector->count) 1562 { 1563 /* 1564 * Unable to get a binding to one of the protseqs 1565 */ 1566 *status = rpc_s_no_protseqs; 1567 } 1568 1569 rpc_protseq_vector_free(&protseq_vector, status); 1570 } 1571 else 1572 { 1573 /* 1574 * A binding was specified. Make sure it's the right kind. Copy it, 1575 * and reset the copy's endpoint, com timeout setting, and auth info 1576 */ 1577 1578 RPC_BINDING_VALIDATE_CLIENT((rpc_binding_rep_p_t) input_binding, status); 1579 1580 rpc_binding_copy(input_binding, output_binding, status); 1581 if (*status != rpc_s_ok) 1582 return; 1583 1584 rpc_binding_reset(*output_binding, status); 1585 if (*status != rpc_s_ok) 1586 { 1587 rpc_binding_free(output_binding, &tmp_st); 1588 return; 1589 } 1590 1591 rpc_mgmt_set_com_timeout (*output_binding, rpc_c_binding_default_timeout, status); 1592 if (*status != rpc_s_ok) 1593 { 1594 rpc_binding_free(output_binding, &tmp_st); 1595 return; 1596 } 1597 1598 rpc_binding_set_auth_info (*output_binding, NULL, rpc_c_authn_level_default, 1599 rpc_c_authn_none, NULL, rpc_c_authz_none, status); 1600 if (*status != rpc_s_ok) 1601 { 1602 rpc_binding_free(output_binding, &tmp_st); 1603 return; 1604 } 1605 1606 } 1607} 1608 1609/* 1610**++ 1611** 1612** ROUTINE NAME: rpc_binding_to_epmap 1613** 1614** SCOPE: PRIVATE 1615** 1616** DESCRIPTION: 1617** 1618** Return a binding to an endpoint mapper. 1619** 1620** INPUTS: 1621** 1622** input_binding Binding from which we should derive a binding on the 1623** endpoint mapper. Can be NULL to mean the endpoint 1624** mapper on the local host. 1625** 1626** INPUTS/OUTPUTS: none 1627** 1628** OUTPUTS: 1629** 1630** output_binding Binding on the endpoint mapper. 1631** 1632** status The result of the operation. 1633** 1634** IMPLICIT INPUTS: none 1635** 1636** IMPLICIT OUTPUTS: none 1637** 1638** FUNCTION VALUE: void 1639** 1640** SIDE EFFECTS: none 1641** 1642**-- 1643**/ 1644PRIVATE void rpc_binding_to_epmap 1645( 1646 rpc_binding_handle_t input_binding, 1647 rpc_binding_handle_t *output_binding, 1648 unsigned32 *status 1649) 1650{ 1651 get_ep_binding(input_binding, output_binding, status); 1652} 1653 1654/* 1655**++ 1656** 1657** ROUTINE NAME: tower_to_if 1658** 1659** SCOPE: INTERNAL 1660** 1661** DESCRIPTION: 1662** 1663** Convert a tower to an interface ID. 1664** 1665** INPUTS: 1666** 1667** tower 1668** 1669** INPUTS/OUTPUTS: none 1670** 1671** OUTPUTS: 1672** 1673** if_id 1674** 1675** status The result of the operation. 1676** 1677** IMPLICIT INPUTS: none 1678** 1679** IMPLICIT OUTPUTS: none 1680** 1681** FUNCTION VALUE: void 1682** 1683** SIDE EFFECTS: none 1684** 1685**-- 1686**/ 1687 1688INTERNAL void tower_to_if_id 1689( 1690 twr_p_t tower, 1691 rpc_if_id_t *if_id, 1692 unsigned32 *status 1693) 1694{ 1695 rpc_tower_ref_t *tref; 1696 unsigned32 tmp_st; 1697 1698 rpc__tower_to_tower_ref(tower, &tref, status); 1699 if (*status != rpc_s_ok) 1700 return; 1701 1702 if (tref->count < RPC_C_NUM_RPC_FLOORS) 1703 { 1704 *status = ept_s_invalid_entry; 1705 return; 1706 } 1707 1708 rpc__tower_flr_to_if_id(tref->floor[0], if_id, status); 1709 1710 rpc__tower_ref_free(&tref, &tmp_st); 1711} 1712 1713/* 1714**++ 1715** 1716** ROUTINE NAME: rpc_ep_resolve_binding 1717** 1718** SCOPE: PUBLIC - declared in rpc.idl 1719** 1720** DESCRIPTION: 1721** 1722** An application calls the rpc_ep_resolve_binding 1723** routine to resolve a partially-bound server binding 1724** handle into a fully-bound binding handle. 1725** 1726** Resolving binding handles requires an interface UUID 1727** and an object UUID (which may be nil). The RPC runtime 1728** requests the RPC daemon (rpcd) on the host specified 1729** by the binding argument to look up an endpoint for 1730** a compatible server instance. To find the endpoint, 1731** the rpcd looks in the endpoint map for the interface 1732** UUID from the if_spec argument and the object UUID 1733** in the binding argument, if any. (For a discussion 1734** on how rpcd locates compatible server instances, see 1735** Chapter 11 in the Functional Spec.) 1736** 1737** The functioning of the resolve-binding operation 1738** depends on whether the specified binding handle is 1739** partially or fully bound. When the client specifies a 1740** partially-bound handle, the resolve-binding operation 1741** has the following possible outcomes: 1742** 1743** o If no compatible server instances are registered 1744** in the endpoint map, the resolve-binding operation 1745** returns the ept_s_not_registered status code. 1746** 1747** o If a compatible server instance is registered in 1748** the endpoint map, the resolve-binding operation 1749** returns a fully-bound binding and the rpc_s_ok 1750** status code. 1751** 1752** When the client specifies a fully-bound binding 1753** handle, the resolve-binding operation returns the 1754** specified binding handle and the rpc_s_ok status code. 1755** The resolve-binding operation does not contact the 1756** rpcd. 1757** 1758** In neither the partially- or fully-bound binding 1759** case, does the resolve-binding operation contact a 1760** compatible server instance. 1761** 1762** 1763** INPUTS: 1764** 1765** if_spec A stub generated data structure specifying the 1766** interface of interest. 1767** 1768** INPUTS/OUTPUTS: none 1769** 1770** binding A partially bound server binding handle to resolve to 1771** a fully bound server binding handle. 1772** 1773** OUTPUTS: 1774** 1775** status Returns the status code from the resolve binding 1776** operation. This status code is a value that indicates 1777** whether the routine completed successfully and, if 1778** not, why. 1779** rpc_s_ok The call completed normally. 1780** ept_s_not_registered No entries found 1781** rpc_s_invalid_binding Invalid binding handle 1782** rpc_s_wrong_kind_of_binding Wrong kind of binding for 1783** operation 1784** rpc_s_rpcd_comm_failure rpc daemon 1785** communications failure 1786** IMPLICIT INPUTS: none 1787** 1788** IMPLICIT OUTPUTS: none 1789** 1790** FUNCTION VALUE: none 1791** 1792** SIDE EFFECTS: 1793** 1794** This routine does not check for concurrent use of the 1795** binding handle. It is up to the user of this routine to 1796** ensure the consistency and correctness of the binding handle 1797** by restricting concurrent use of it across multiple threads. 1798** This is the same guarantee the user must provide while modifying 1799** other binding fields, such as the object UUID, endpoint, and 1800** auth info. 1801** 1802**-- 1803**/ 1804 1805PUBLIC void rpc_ep_resolve_binding 1806( 1807 rpc_binding_handle_t binding_h, 1808 rpc_if_handle_t if_spec_h, 1809 unsigned32 *status 1810) 1811{ 1812 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 1813 1814 assert(binding_rep != NULL); 1815 1816 CODING_ERROR (status); 1817 RPC_VERIFY_INIT (); 1818 RPC_BINDING_VALIDATE_CLIENT (binding_rep, status); 1819 if (*status != rpc_s_ok) 1820 { 1821 return; 1822 } 1823 1824 /* 1825 * Determine whther the specified binding handle is 1826 * partially or fully bound. 1827 */ 1828 if (!binding_rep->addr_has_endpoint) 1829 { 1830 /* 1831 * The binding is partially bound. Prevent other threads 1832 * from using this handle while we are trying to resolve 1833 * it. 1834 */ 1835 ep_get_endpoint ((rpc_if_rep_p_t) if_spec_h, binding_rep, status); 1836 } 1837 else 1838 { 1839 /* 1840 * The binding is fully bound. Just return it. 1841 */ 1842 *status = rpc_s_ok; 1843 } 1844} 1845 1846 1847/* 1848**++ 1849** 1850** ROUTINE NAME: ep_get_endpoint 1851** 1852** SCOPE: INTERNAL - declared locally 1853** 1854** DESCRIPTION: 1855** 1856** Find the correct endpoint information and plug it into the 1857** binding rep. This routine is called by rpc_ep_resolve_binding 1858** when the binding is not fully bound. 1859** 1860** We first check the i/f spec to see if the endpoint information 1861** is there to use. If not, we make an RPC call to the endpoint 1862** mapper on the node specified in the binding handle to obtain 1863** the endpoint information for the specified interface. Then we 1864** plug in the endpoint (returned from ep_map()) in the binding 1865** handle. 1866** 1867** 1868** INPUTS: 1869** 1870** if_r a pointer to the interface spec of interest 1871** 1872** INPUTS/OUTPUTS: 1873** 1874** binding_r a pointer to the binding rep which requires an endpoint 1875** 1876** OUTPUTS: none 1877** 1878** st The return status of this routine. 1879** rpc_s_ok The call completed normally. 1880** rpc_s_rpcd_comm_failure rpc daemon 1881** communications failure 1882** IMPLICIT INPUTS: none 1883** 1884** IMPLICIT OUTPUTS: none 1885** 1886** FUNCTION VALUE: none 1887** 1888** SIDE EFFECTS: none 1889** 1890**-- 1891**/ 1892 1893INTERNAL void ep_get_endpoint 1894( 1895 rpc_if_rep_p_t if_r, 1896 rpc_binding_rep_p_t binding_r, 1897 unsigned32 *st 1898) 1899{ 1900 unsigned32 temp_status; 1901 unsigned_char_p_t endpoint = NULL; 1902 ept_lookup_handle_t map_lookup_handle; 1903 rpc_addr_p_t *rpc_addr; 1904 unsigned32 saved_timeout; 1905 idl_uuid_t saved_object_uuid; 1906 rpc_tower_ref_vector_p_t tower_vector = NULL; 1907 twr_p_t map_tower = NULL; 1908 twr_p_t * volatile towers = NULL; 1909 unsigned32 num_towers = 0; 1910 rpc_addr_p_t tower_rpc_addr = NULL; 1911 rpc_auth_info_t *saved_auth_info; 1912 unsigned32 tower_to_use; 1913 unsigned32 i, j; 1914 volatile boolean32 full_restore_flag = true; 1915 boolean32 map_lookup; 1916 volatile boolean32 free_prot_version = false; 1917 rpc_ss_p_alloc_t old_allocate; 1918 rpc_ss_p_alloc_t tmp_allocate; 1919 rpc_ss_p_free_t old_free; 1920 rpc_ss_p_free_t tmp_free; 1921 1922// DO_NOT_CLOBBER(towers); 1923 towers = NULL; 1924// DO_NOT_CLOBBER(full_restore_flag); 1925 full_restore_flag = true; 1926// DO_NOT_CLOBBER(free_prot_version); 1927 free_prot_version = true; 1928 1929 CODING_ERROR (st); 1930 1931 rpc_addr = &binding_r->rpc_addr; 1932 1933 /* 1934 * Get the endpoint from the i/f spec, if present. 1935 */ 1936 rpc__if_set_wk_endpoint (if_r, rpc_addr, st); 1937 if (*st == rpc_s_ok) 1938 { 1939 /* 1940 * Notify the protocol service that the binding has changed. 1941 */ 1942 (*rpc_g_protocol_id[binding_r->protocol_id].binding_epv 1943 ->binding_changed) (binding_r, st); 1944 1945 if (*st != rpc_s_ok) 1946 { 1947 return; 1948 } 1949 1950 /* 1951 * The binding now contains the endpoint in the 1952 * interface spec. 1953 */ 1954 binding_r->addr_has_endpoint = true; 1955 1956 return; 1957 } 1958 1959 if (*st != rpc_s_endpoint_not_found) 1960 { 1961 return; 1962 } 1963 else 1964 { 1965 /* 1966 * Save away the binding object UUID before 1967 * making the endpoint map call. The endpoint map 1968 * call must be made with a binding which either 1969 * has a nil object UUID or the well-known object 1970 * UUID for this instantiation of the endpoint 1971 * database. 1972 */ 1973 rpc_binding_inq_object ((rpc_binding_handle_t) binding_r, 1974 &saved_object_uuid, 1975 st); 1976 1977 if (*st != rpc_s_ok) 1978 { 1979 return; 1980 } 1981 1982 /* 1983 * Save away the com timeout in the binding just in case 1984 * it's set to infinite. We really don't want to try 1985 * forever to reach the endpoint mapper. 1986 */ 1987 rpc_mgmt_inq_com_timeout ((rpc_binding_handle_t) binding_r, 1988 &saved_timeout, st); 1989 1990 if (*st != rpc_s_ok) 1991 { 1992 return; 1993 } 1994 1995 /* 1996 * Save the auth info on the binding. 1997 * The call to the endpoint mapper will 1998 * not be authenticated. 1999 */ 2000 saved_auth_info = binding_r->auth_info; 2001 2002 /* 2003 * Set the binding object to nil. 2004 */ 2005 rpc_binding_set_object ((rpc_binding_handle_t) binding_r, 2006 &uuid_g_nil_uuid, 2007 st); 2008 2009 if (*st != rpc_s_ok) 2010 { 2011 goto CLEANUP; 2012 } 2013 2014 rpc_mgmt_set_com_timeout ((rpc_binding_handle_t) binding_r, 2015 rpc_c_binding_default_timeout, st); 2016 2017 if (*st != rpc_s_ok) 2018 { 2019 goto CLEANUP; 2020 } 2021 2022 binding_r->auth_info = NULL; 2023 2024 /* 2025 * Construct a (fully-bound) handle to the Endpoint 2026 * Mapper at the target node. 2027 * We do this by taking the partially bound handle 2028 * and setting the endpoint to the well-known 2029 * endpoint associated with the EP interface 2030 * (for the designated protocol sequence). 2031 */ 2032 rpc__if_set_wk_endpoint ((rpc_if_rep_p_t) ept_v3_0_c_ifspec, 2033 rpc_addr, 2034 st); 2035 if (*st != rpc_s_ok) 2036 { 2037 goto CLEANUP; 2038 } 2039 /* 2040 * If this binding handle doesn't have a protocol version 2041 * attached to it (probably a string binding), then 2042 * create one that will insure we will get an endpoint. 2043 */ 2044 if (binding_r->protocol_version == NULL) 2045 { 2046 unsigned8 temp_prot_id; 2047 unsigned32 temp_vers_major, 2048 temp_vers_minor; 2049 2050 rpc__network_inq_prot_version(binding_r->rpc_addr->rpc_protseq_id, 2051 &temp_prot_id, 2052 &temp_vers_major, 2053 &temp_vers_minor, 2054 st); 2055 2056 if (*st != rpc_s_ok) 2057 { 2058 goto CLEANUP; 2059 } 2060 2061 /* 2062 * This is ugly, but if we are talking to a 1.0.x rpcd, 2063 * it wont give us an endpoint if our minor number is 2064 * higher than the servers. 2065 */ 2066 rpc__binding_prot_version_alloc(&(binding_r->protocol_version), 2067 temp_vers_major, 2068 0, 2069 st); 2070 if (*st != rpc_s_ok) 2071 { 2072 goto CLEANUP; 2073 } 2074 2075 /* remember to free this when we get the endpoint */ 2076 free_prot_version = true; 2077 } 2078 2079 /* 2080 * Notify the protocol service that the binding 2081 * has changed. 2082 */ 2083 (*rpc_g_protocol_id[binding_r->protocol_id].binding_epv 2084 ->binding_changed) (binding_r, st); 2085 2086 if (*st != rpc_s_ok) 2087 { 2088 goto CLEANUP; 2089 } 2090 2091 binding_r->addr_has_endpoint = true; 2092 2093 /* 2094 * In order to lookup entries in the endpoint mapper 2095 * database we need to provide a map tower which it will 2096 * use as a lookup key. The important fields in the tower 2097 * are the interface UUID and version, data rep, protocol 2098 * sequence and RPC protocol version. To create the map 2099 * tower the binding given by the client, which contains 2100 * the correct protocol sequence and the interface spec, 2101 * which contains the interface UUID and version and data 2102 * rep(s). This information will be converted into a 2103 * vector of tower ref structures (one for each data rep). 2104 * These tower ref structures can then be converted into a 2105 * real tower, the map tower. The output of the endpoint 2106 * map will also be a tower containing the desired 2107 * endpoint. This tower will be converted into an RPC 2108 * address, from which the endpoint will be extracted. 2109 * Finally the endpoint will be set in the original 2110 * binding. 2111 * 2112 * NOTE: When logic to iterate through the endpoint 2113 * mapper database if the presentation negotiation fails 2114 * is added an iteration will have to be done for each 2115 * tower ref gotten from the binding,ifspec tuple. For 2116 * right now only the first tower ref in the vector is 2117 * looked at and no iteration is done with it. 2118 */ 2119 rpc__tower_ref_vec_from_binding (if_r, 2120 (rpc_binding_handle_t )binding_r, 2121 &tower_vector, st); 2122 2123 if (*st != rpc_s_ok) 2124 { 2125 goto CLEANUP; 2126 } 2127 2128 rpc__tower_from_tower_ref (tower_vector->tower[0], 2129 &map_tower, st); 2130 2131 if (*st != rpc_s_ok) 2132 { 2133 goto CLEANUP; 2134 } 2135 2136 /* 2137 * We want to get *all* of the compatible towers back from 2138 * the ep map so that we can randomly select one to provide 2139 * an endpoint to the caller's binding handle. 2140 * We get all to the towers by allocating memory to hold 2141 * MAX_TOWERS compatible towers. If it turns out that 2142 * MAX_TOWERS is not sufficient, then we free the towers 2143 * and try again allowing for MAX_TOWERS x 2 towers. 2144 * This continues ( x 3; x 4; ...) until we get them all 2145 * in one call. 2146 */ 2147 DCETHREAD_TRY 2148 { 2149 /* 2150 * The increment i specifies the multiples of MAX_TOWERS 2151 * towers to get. 2152 * 2153 * The map lookup boolean signifies whether we have to try 2154 * again with a larger towers size. 2155 * 2156 * The map lookup handle, which is really a context handle, must be 2157 * initialized to NULL unless we are iterating. 2158 */ 2159 for (i = 1, map_lookup = true, map_lookup_handle = NULL; 2160 map_lookup == true; 2161 ++i) 2162 { 2163 RPC_MEM_ALLOC ( 2164 towers, 2165 twr_p_t *, 2166 sizeof(twr_p_t) * (MAX_TOWERS * i), 2167 RPC_C_MEM_TOWER, 2168 RPC_C_MEM_NOWAIT); 2169 /* 2170 * Set all the pointers in the array to NULL. 2171 */ 2172 memset (towers, 0, sizeof(twr_p_t) * (MAX_TOWERS * i)); 2173 2174 /* 2175 * Force the stub to use a particular form of memory 2176 * allocation. 2177 */ 2178 rpc_ss_swap_client_alloc_free ( 2179 rpc__ep_mem_alloc, rpc__ep_mem_free, 2180 &old_allocate, &old_free); 2181 2182 (*ept_v3_0_c_epv.ept_map) 2183 ((rpc_binding_handle_t) binding_r, 2184 &saved_object_uuid, 2185 map_tower, 2186 &map_lookup_handle, 2187 MAX_TOWERS * i, 2188 &num_towers, 2189 towers, 2190 st); 2191 2192 /* 2193 * Restore the memory allocation scheme in effect before 2194 * we got here 2195 */ 2196 rpc_ss_swap_client_alloc_free ( 2197 old_allocate, old_free, 2198 &tmp_allocate, &tmp_free); 2199 2200 /* 2201 * If we got all of the compatible bindings, we're 2202 * done with ep map. 2203 * Otherwise, let's get rid of the ones returned (this was 2204 * memory allocated by the stub) and we'll try again. 2205 */ 2206 if (map_lookup_handle == NULL) 2207 { 2208 map_lookup = false; 2209 } 2210 else 2211 { 2212 for (j = 0; j < num_towers; ++j) 2213 { 2214 rpc__ep_mem_free (NULL, (dce_pointer_t) towers[j]); 2215 } 2216 2217 RPC_MEM_FREE (towers, RPC_C_MEM_TOWER); 2218 2219 /* 2220 * So we'll know what to do for cleanup. 2221 */ 2222 towers = NULL; 2223 2224 /* 2225 * Free the lookup handle at rpcd. 2226 */ 2227 (*ept_v3_0_c_epv.ept_lookup_handle_free) 2228 ((rpc_binding_handle_t) binding_r, 2229 &map_lookup_handle, 2230 &temp_status); 2231 2232 if (temp_status == rpc_s_call_cancelled) 2233 dcethread_interrupt_throw(dcethread_self()); 2234 2235 /* 2236 * We'll ignore any problem in trying to free the handle 2237 * (for example, can't reach rpcd). 2238 */ 2239#ifdef DEBUG 2240 if (temp_status != rpc_s_ok) 2241 { 2242 RPC_DBG_PRINTF (rpc_e_dbg_general, 1, 2243 ("(ep_get_endpoint) call_rep->none binding_rep->%p ept_lookup_handle_free returned %x\n", 2244 binding_r, temp_status)); 2245 } 2246#endif 2247 } 2248 } 2249 } 2250 DCETHREAD_CATCH_ALL(THIS_CATCH) 2251 { 2252 /* 2253 * Report any exception as: 2254 */ 2255 *st = rpc_s_rpcd_comm_failure; 2256 } 2257 DCETHREAD_ENDTRY 2258 2259 if (*st != rpc_s_ok) 2260 { 2261 goto CLEANUP; 2262 } 2263 2264 /* 2265 * From the returned compatible towers, randomly pick one. 2266 */ 2267 tower_to_use = RPC_RANDOM_GET (0, num_towers - 1); 2268 2269 assert (&towers[tower_to_use] != NULL); 2270 rpc__naf_tower_flrs_to_addr ( 2271 &(towers[tower_to_use]->tower_octet_string[0]), 2272 &tower_rpc_addr, 2273 st); 2274 2275 if (*st != rpc_s_ok) 2276 { 2277 goto CLEANUP; 2278 } 2279 2280 rpc__naf_addr_inq_endpoint (tower_rpc_addr, &endpoint, st); 2281 2282 if (*st != rpc_s_ok) 2283 { 2284 goto CLEANUP; 2285 } 2286 2287 /* 2288 * The binding currently contains the rpcd boot time. 2289 * To avoid a "wrong boot time" error over dg when the 2290 * returned binding (with selected endpoint) is used to make 2291 * a rpc, reset the binding (before adding the server 2292 * endpoint) to clear the boot time. 2293 */ 2294 rpc_binding_reset ((rpc_binding_handle_t) binding_r, st); 2295 2296 if (*st != rpc_s_ok) 2297 { 2298 goto CLEANUP; 2299 } 2300 2301 rpc__naf_addr_set_endpoint (endpoint, rpc_addr, st); 2302 2303 if (*st != rpc_s_ok) 2304 { 2305 goto CLEANUP; 2306 } 2307 2308 /* 2309 * Resetting the binding also reset the has-endpoint flag. 2310 * We need to turn it back on. 2311 */ 2312 binding_r->addr_has_endpoint = true; 2313 2314#ifdef DEBUG 2315 RPC_DBG_PRINTF (rpc_e_dbg_general, 1, 2316 ("(ep_get_endpoint) call_rep->none binding_rep->%p endpoint mapper returned %s\n", 2317 binding_r, endpoint)); 2318#endif 2319 2320 /* 2321 * Notify the protocol service that the binding has changed. 2322 */ 2323 (*rpc_g_protocol_id[binding_r->protocol_id].binding_epv 2324 ->binding_changed) (binding_r, st); 2325 2326 if (*st != rpc_s_ok) 2327 { 2328 goto CLEANUP; 2329 } 2330 2331 full_restore_flag = false; 2332 } 2333 2334CLEANUP: 2335 2336 /* 2337 * If an error occurred, restore the caller's binding back to 2338 * its original condition before returning. 2339 */ 2340 if (full_restore_flag) 2341 { 2342 binding_r->addr_has_endpoint = false; 2343 rpc__naf_addr_set_endpoint ((unsigned_char_p_t) "", rpc_addr, 2344 &temp_status); 2345 } 2346 2347 if (towers != NULL) 2348 { 2349 for (i = 0; i < num_towers; ++i) 2350 { 2351 if (towers[i] != NULL) 2352 { 2353 rpc__ep_mem_free (NULL, (dce_pointer_t) towers[i]); 2354 } 2355 } 2356 2357 RPC_MEM_FREE (towers, RPC_C_MEM_TOWER); 2358 } 2359 2360 /* 2361 * Free allocated protocol version 2362 */ 2363 if (free_prot_version == true) 2364 { 2365 rpc__binding_prot_version_free (&(binding_r->protocol_version)); 2366 } 2367 2368 /* 2369 * Restore the saved auth info. 2370 */ 2371 binding_r->auth_info = saved_auth_info; 2372 2373 /* 2374 * Restore the saved binding com timeout. 2375 */ 2376 rpc_mgmt_set_com_timeout ((rpc_binding_handle_t) binding_r, 2377 saved_timeout, &temp_status); 2378 2379 if (temp_status != rpc_s_ok) 2380 { 2381 goto EXIT; 2382 } 2383 2384 /* 2385 * Restore the saved binding object UUID. 2386 */ 2387 rpc_binding_set_object ((rpc_binding_handle_t) binding_r, 2388 &saved_object_uuid, &temp_status); 2389 2390 if (temp_status != rpc_s_ok) 2391 { 2392 goto EXIT; 2393 } 2394 2395 if (map_tower != NULL) 2396 { 2397 rpc__tower_free (&map_tower, &temp_status); 2398 2399 if (temp_status != rpc_s_ok) 2400 { 2401 goto EXIT; 2402 } 2403 } 2404 2405 if (tower_vector != NULL) 2406 { 2407 rpc__tower_ref_vec_free (&tower_vector, &temp_status); 2408 2409 if (temp_status != rpc_s_ok) 2410 { 2411 goto EXIT; 2412 } 2413 } 2414 2415 if (tower_rpc_addr != NULL) 2416 { 2417 rpc__naf_addr_free (&tower_rpc_addr, &temp_status); 2418 2419 if (temp_status != rpc_s_ok) 2420 { 2421 goto EXIT; 2422 } 2423 } 2424 2425 if (endpoint != NULL) 2426 { 2427 rpc_string_free (&endpoint, &temp_status); 2428 2429 if (temp_status != rpc_s_ok) 2430 { 2431 goto EXIT; 2432 } 2433 } 2434 2435EXIT: 2436 if (*st != rpc_s_ok) 2437 { 2438 return; 2439 } 2440 else 2441 { 2442 *st = temp_status; 2443 return; 2444 } 2445} 2446 2447/* 2448**++ 2449** 2450** ROUTINE NAME: rpc__ep_mem_alloc 2451** 2452** SCOPE: INTERNAL 2453** 2454** DESCRIPTION: 2455** 2456** Wrapper around RPC_MEM_ALLOC to use in call to 2457** rpc_ss_swap_client_alloc_free. 2458** 2459** INPUTS: 2460** 2461** size number of bytes to allocate 2462** 2463** INPUTS/OUTPUTS: none 2464** 2465** OUTPUTS: none 2466** 2467** IMPLICIT INPUTS: none 2468** 2469** IMPLICIT OUTPUTS: none 2470** 2471** FUNCTION VALUE: idl_void_p_t 2472** 2473** return pointer to allocated storage 2474** 2475** SIDE EFFECTS: none 2476** 2477**-- 2478**/ 2479 2480INTERNAL idl_void_p_t rpc__ep_mem_alloc 2481( 2482 idl_void_p_t context ATTRIBUTE_UNUSED, 2483 idl_size_t size 2484) 2485{ 2486 idl_void_p_t ptr; 2487 2488 RPC_MEM_ALLOC ( 2489 ptr, 2490 idl_void_p_t, 2491 size, 2492 RPC_C_MEM_TOWER, 2493 RPC_C_MEM_WAITOK); 2494 2495 return (ptr); 2496} 2497 2498/* 2499**++ 2500** 2501** ROUTINE NAME: rpc__ep_mem_free 2502** 2503** SCOPE: INTERNAL 2504** 2505** DESCRIPTION: 2506** 2507** Wrapper around RPC_MEM_FREE to use in call to 2508** rpc_ss_swap_client_alloc_free. 2509** 2510** INPUTS: 2511** 2512** ptr storage to free 2513** 2514** INPUTS/OUTPUTS: none 2515** 2516** OUTPUTS: none 2517** 2518** IMPLICIT INPUTS: none 2519** 2520** IMPLICIT OUTPUTS: none 2521** 2522** FUNCTION VALUE: none 2523** 2524** SIDE EFFECTS: none 2525** 2526**-- 2527**/ 2528 2529INTERNAL void rpc__ep_mem_free 2530( 2531 idl_void_p_t context ATTRIBUTE_UNUSED, 2532 dce_pointer_t ptr 2533) 2534{ 2535 RPC_MEM_FREE (ptr, RPC_C_MEM_TOWER); 2536} 2537