1/* 2 * Copyright (c) 2010-2011 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** combind.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** Definition of the Binding Services for the Common Communication 90** Services component. These routines are called by applications to 91** manipulate Binding Rep data structures required by the runtime. 92** 93** 94*/ 95 96#include <commonp.h> /* Common declarations for all RPC runtime */ 97#include <com.h> /* Common communications services */ 98#include <comp.h> /* Private communications services */ 99#include <cs_s.h> /* I18N codesets definitions */ 100#include <comtwrflr.h> 101 102 103/* 104**++ 105** 106** ROUTINE NAME: rpc__binding_free 107** 108** SCOPE: PRIVATE - declared in com.h 109** 110** DESCRIPTION: 111** 112** This routine will really free the Binding Rep memory - this routine 113** should not be called directly; RPC_BINDING_RELEASE() should be used. 114** Since a Binding Rep's size is RPC Protocol Service-specific the RPC 115** Protocol Service is called to do the actual free. 116** 117** INPUTS: 118** 119** binding_rep The binding rep pointer which points to the binding 120** rep data structure to be freed. 121** 122** INPUTS/OUTPUTS: none 123** 124** OUTPUTS: 125** 126** status A value indicating the status of the routine. 127** 128** rpc_s_ok The call was successful. 129** 130** IMPLICIT INPUTS: none 131** 132** IMPLICIT OUTPUTS: none 133** 134** FUNCTION VALUE: void 135** 136** SIDE EFFECTS: none 137** 138**-- 139**/ 140 141PRIVATE void rpc__binding_free 142( 143 rpc_binding_rep_p_t *binding_rep_p, 144 unsigned32 *status 145) 146{ 147 rpc_binding_rep_p_t binding_rep = *binding_rep_p; 148 unsigned32 temp_status = rpc_s_ok; 149 rpc_cs_method_eval_p_t method_p ATTRIBUTE_UNUSED; 150 rpc_cs_tags_eval_p_t tags_p ATTRIBUTE_UNUSED; 151 152 CODING_ERROR (status); 153 154 /* 155 * The handle must be locked so that we can "atomically" 156 * free it. 157 */ 158 RPC_LOCK_ASSERT(0); 159 160 /* 161 * see if an RPC address exists in this binding 162 */ 163 if (binding_rep->rpc_addr != NULL) 164 { 165 /* 166 * if so, ask the NAF extension service to free the RPC address 167 */ 168 (*rpc_g_naf_id[binding_rep->rpc_addr->sa.family].epv 169 ->naf_addr_free) (&(binding_rep->rpc_addr), status); 170 if (*status != rpc_s_ok) return; 171 } 172 173 /* 174 * see if we have a protocol version 175 */ 176 if (binding_rep->protocol_version != NULL) 177 { 178 rpc__binding_prot_version_free(&(binding_rep->protocol_version)); 179 } 180 181#ifdef PD_BUILD 182 /* 183 * check code sets I14Y 184 */ 185 if (binding_rep->extended_bind_flag == RPC_C_BH_EXTENDED_CODESETS) 186 { 187 /* Release codesets relating binding information. 188 * Determine the data structure 189 */ 190 switch (binding_rep->cs_eval.key) 191 { 192 case RPC_CS_EVAL_METHOD: 193 method_p = &binding_rep->cs_eval.tagged_union.method_key; 194 195 if (method_p->server != NULL) 196 rpc_ns_mgmt_free_codesets ( 197 &(method_p->server), 198 &temp_status ); 199 200 if (method_p->client != NULL) 201 rpc_ns_mgmt_free_codesets ( 202 &(method_p->client), 203 &temp_status ); 204 break; 205 206 case RPC_CS_EVAL_TAGS: 207 208 break; 209 210 default: 211 temp_status = rpc_s_ss_invalid_codeset_tag; 212 break; 213 } 214 } 215#endif 216 217 /* 218 * if we have any authentication info, free it up now. 219 */ 220 rpc__auth_info_binding_release(binding_rep); 221 222 /* 223 * if we have transport information, free it up now 224 */ 225 if (binding_rep->transport_info) 226 { 227 rpc__transport_info_release(binding_rep->transport_info); 228 } 229 230 /* 231 * Free the name service-specific part of the binding. 232 */ 233 if (binding_rep->ns_specific != NULL) 234 (*rpc_g_ns_specific_free_fn) (&binding_rep->ns_specific); 235 236 /* 237 * then ask the protocol service to free the binding rep and 238 * NULL the reference. 239 */ 240 (*rpc_g_protocol_id[binding_rep->protocol_id].binding_epv 241 ->binding_free) (binding_rep_p, status); 242 243 if ((temp_status != rpc_s_ok) && (*status == rpc_s_ok)) 244 *status = temp_status; 245} 246 247 248/* 249**++ 250** 251** ROUTINE NAME: rpc_binding_free 252** 253** SCOPE: PUBLIC - declared in rpc.idl 254** 255** DESCRIPTION: 256** 257** This routine will release the reference on the Binding Rep and free 258** the rep when no more references exist. A NULL pointer will be 259** returned. Most runtime internal operations that want to release a binding 260** handle reference should probably use RPC_BINDING_RELEASE(), not this 261** routine. 262** 263** INPUTS: none 264** 265** INPUTS/OUTPUTS: 266** 267** binding_h The binding handle which points to the binding 268** rep data structure to be freed. 269** 270** OUTPUTS: 271** 272** status A value indicating the status of the routine. 273** 274** rpc_s_ok The call was successful. 275** rpc_s_invalid_binding 276** RPC Protocol ID in binding handle was invalid. 277** rpc_s_coding_error 278** 279** IMPLICIT INPUTS: none 280** 281** IMPLICIT OUTPUTS: none 282** 283** FUNCTION VALUE: void 284** 285** SIDE EFFECTS: none 286** 287**-- 288**/ 289 290PUBLIC void rpc_binding_free 291( 292 rpc_binding_handle_t *binding_h, 293 unsigned32 *status 294) 295{ 296 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) *binding_h; 297 298 assert(binding_rep != NULL); 299 300 CODING_ERROR (status); 301 RPC_VERIFY_INIT (); 302 303 RPC_BINDING_VALIDATE_CLIENT(binding_rep, status); 304 if (*status != rpc_s_ok) 305 return; 306 307 /* 308 * We need to lock the handle so that we can "atomically" 309 * release it. 310 */ 311 RPC_LOCK(0); 312 313 /* 314 * Release and NULL the reference (possibly free the handle). 315 */ 316 RPC_BINDING_RELEASE((rpc_binding_rep_p_t *) binding_h, status); 317 318 RPC_UNLOCK(0); 319} 320 321/* 322**++ 323** 324** ROUTINE NAME: rpc_binding_vector_free 325** 326** SCOPE: PUBLIC - declared in rpc.idl 327** 328** DESCRIPTION: 329** 330** This routine will free the Binding Rep pointed to by each non-NULL 331** entry in the vector array. The vector memory itself is then freed. 332** 333** INPUTS: none 334** 335** INPUTS/OUTPUTS: 336** 337** binding_vec A vector of pointers to binding rep structures. 338** 339** OUTPUTS: 340** 341** status A value indicating the status of the routine. 342** 343** rpc_s_ok The call was successful. 344** rpc_s_coding_error 345** rpc_s_invalid_arg 346** 347** IMPLICIT INPUTS: none 348** 349** IMPLICIT OUTPUTS: none 350** 351** FUNCTION VALUE: void 352** 353** SIDE EFFECTS: none 354** 355**-- 356**/ 357 358PUBLIC void rpc_binding_vector_free 359( 360 rpc_binding_vector_p_t *binding_vec, 361 unsigned32 *status 362) 363{ 364 unsigned32 i; 365 366 CODING_ERROR (status); 367 RPC_VERIFY_INIT (); 368 369 /* 370 * check to see if binding_vec is NULL, and if so, 371 * return with an error status 372 */ 373 if (binding_vec == NULL) 374 { 375 *status = rpc_s_invalid_arg; 376 return; 377 } 378 379 /* 380 * free each element in the vector array (that's non-NULL) 381 */ 382 for (i = 0; i < (*binding_vec)->count; i++) 383 { 384 if ((*binding_vec)->binding_h[i] != NULL) 385 { 386 rpc_binding_free (&(*binding_vec)->binding_h[i], status); 387 if (*status != rpc_s_ok) return; 388 } 389 } 390 391 /* 392 * now free the vector memory itself 393 */ 394 RPC_MEM_FREE (*binding_vec, RPC_C_MEM_BINDING_VEC); 395 396 *binding_vec = NULL; 397 398 *status = rpc_s_ok; 399} 400 401/* 402**++ 403** 404** ROUTINE NAME: rpc_binding_set_object 405** 406** SCOPE: PUBLIC - declared in rpc.idl 407** 408** DESCRIPTION: 409** 410** This routine will set the object UUID field in the Binding Rep to the 411** object UUID given. The RPC Protocol Service identified by the RPC 412** Protocol ID in the Binding Rep will be notified that the Binding Rep 413** has changed. 414** 415** INPUTS: 416** 417** binding_h The binding handle which points to the binding 418** rep data structure to be modified. 419** 420** object_uuid The unique identifier of an object to which an RPC 421** may be made. 422** 423** INPUTS/OUTPUTS: none 424** 425** OUTPUTS: 426** 427** status A value indicating the status of the routine. 428** 429** rpc_s_ok The call was successful. 430** rpc_s_invalid_binding 431** RPC Protocol ID in binding handle was invalid. 432** rpc_s_coding_error 433** 434** IMPLICIT INPUTS: none 435** 436** IMPLICIT OUTPUTS: none 437** 438** FUNCTION VALUE: void 439** 440** SIDE EFFECTS: none 441** 442**-- 443**/ 444 445PUBLIC void rpc_binding_set_object 446( 447 rpc_binding_handle_t binding_h, 448 uuid_p_t object_uuid, 449 unsigned32 *status 450) 451{ 452 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 453 454 assert(binding_rep != NULL); 455 456 CODING_ERROR (status); 457 RPC_VERIFY_INIT (); 458 459 RPC_BINDING_VALIDATE_CLIENT(binding_rep, status); 460 if (*status != rpc_s_ok) 461 return; 462 463 /* 464 * copy the new object UUID into the binding rep 465 * (note: a NULL object uuid pointer is treated as a nil uuid) 466 */ 467 if (object_uuid != NULL) 468 { 469 binding_rep->obj = *object_uuid; 470 } 471 else 472 { 473 uuid_create_nil (&(binding_rep->obj), status); 474 } 475 476 /* 477 * notify the protocol service that the binding has changed 478 */ 479 (*rpc_g_protocol_id[binding_rep->protocol_id].binding_epv 480 ->binding_changed) (binding_rep, status); 481} 482 483/* 484**++ 485** 486** ROUTINE NAME: rpc_binding_inq_object 487** 488** SCOPE: PUBLIC - declared in rpc.idl 489** 490** DESCRIPTION: 491** 492** This routine will inquire what the object UUID is in a Binding Rep. 493** 494** INPUTS: 495** 496** binding_h The binding handle which points to the binding 497** rep data structure to be read. 498** 499** INPUTS/OUTPUTS: none 500** 501** OUTPUTS: 502** 503** object_uuid The unique identifier of an object to which an RPC 504** may be made. 505** 506** status A value indicating the status of the routine. 507** 508** rpc_s_ok The call was successful. 509** rpc_s_invalid_binding 510** RPC Protocol ID in binding handle was invalid. 511** rpc_s_coding_error 512** 513** IMPLICIT INPUTS: none 514** 515** IMPLICIT OUTPUTS: none 516** 517** FUNCTION VALUE: void 518** 519** SIDE EFFECTS: none 520** 521**-- 522**/ 523 524PUBLIC void rpc_binding_inq_object 525( 526 rpc_binding_handle_t binding_h, 527 idl_uuid_t *object_uuid, 528 unsigned32 *status 529) 530{ 531 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 532 533 assert(binding_rep != NULL); 534 535 CODING_ERROR (status); 536 RPC_VERIFY_INIT (); 537 538 RPC_BINDING_VALIDATE(binding_rep, status); 539 if (*status != rpc_s_ok) 540 return; 541 542 *object_uuid = binding_rep->obj; 543 544 *status = rpc_s_ok; 545} 546 547/* 548**++ 549** 550** ROUTINE NAME: rpc_binding_reset 551** 552** SCOPE: PUBLIC - declared in rpc.idl 553** 554** DESCRIPTION: 555** 556** This routine will clear the endpoint in the RPC address of the Binding 557** Rep. The Network Address Family Extension Service identified by the 558** NAF ID in the RPC address will be called to actually clear the endpoint 559** since its format is NAF-specific. Finally the RPC Protocol Service 560** identifed by the RPC Protocol ID in the Binding Rep will be notified 561** that the Binding Rep has changed. 562** 563** INPUTS: 564** 565** binding_h The binding handle which points to the binding 566** rep data structure to be modified. 567** 568** INPUTS/OUTPUTS: none 569** 570** OUTPUTS: 571** 572** status A value indicating the status of the routine. 573** 574** rpc_s_ok The call was successful. 575** rpc_s_invalid_binding 576** RPC Protocol ID in binding handle was invalid. 577** rpc_s_coding_error 578** 579** IMPLICIT INPUTS: none 580** 581** IMPLICIT OUTPUTS: none 582** 583** FUNCTION VALUE: void 584** 585** SIDE EFFECTS: none 586** 587**-- 588**/ 589 590PUBLIC void rpc_binding_reset 591( 592 rpc_binding_handle_t binding_h, 593 unsigned32 *status 594) 595{ 596 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 597 598 assert(binding_rep != NULL); 599 600 CODING_ERROR (status); 601 RPC_VERIFY_INIT (); 602 603 RPC_BINDING_VALIDATE_CLIENT(binding_rep, status); 604 if (*status != rpc_s_ok) 605 return; 606 607 /* 608 * There is no longer a server instance associated with the binding. 609 */ 610 611 RPC_LOCK(0); 612 binding_rep->bound_server_instance = false; 613 RPC_UNLOCK(0); 614 615 /* 616 * if binding endpoint is not set, don't do anything 617 */ 618 if (!binding_rep->addr_has_endpoint) 619 { 620 *status = rpc_s_ok; 621 return; 622 } 623 624 assert(binding_rep->rpc_addr != NULL); 625 626 /* 627 * Tell the NAF extension service to clear the endpoint. A zero 628 * length string *must* be passed in to naf_addr_set_endpoint to 629 * clear the endpoint. Do *not* pass in NULL. This will generate a 630 * dynamic endpoint in certain nafs. 631 */ 632 (*rpc_g_naf_id[binding_rep->rpc_addr->sa.family].epv 633 ->naf_addr_set_endpoint) 634 ((unsigned_char_p_t) "", &(binding_rep->rpc_addr), status); 635 if (*status != rpc_s_ok) return; 636 637 /* 638 * clear the endpoint flag in the binding rep 639 */ 640 binding_rep->addr_has_endpoint = false; 641 642 /* 643 * notify the protocol service that the binding rep has been reset 644 */ 645 (*rpc_g_protocol_id[binding_rep->protocol_id].binding_epv 646 ->binding_reset) (binding_rep, status); 647} 648 649/* 650**++ 651** 652** ROUTINE NAME: rpc_binding_copy 653** 654** SCOPE: PUBLIC - declared in rpc.idl 655** 656** DESCRIPTION: 657** 658** This routine will allocate a new Binding Rep through the RPC Protocol 659** Service. The common part of the Binding Rep will then be filled in and 660** the RPC Protocol Service will be called to initialize the RPC Protocol 661** Service-specific part of the Binding Rep. 662** 663** INPUTS: 664** 665** src_binding_h The binding handle which points to the source 666** binding rep data structure to be copied. 667** 668** INPUTS/OUTPUTS: none 669** 670** OUTPUTS: 671** 672** dst_binding_h The binding handle which points to the destination 673** binding rep data structure to be created. 674** 675** status A value indicating the status of the routine. 676** 677** rpc_s_ok The call was successful. 678** rpc_s_invalid_binding 679** RPC Protocol ID in binding handle was invalid. 680** rpc_s_coding_error 681** 682** IMPLICIT INPUTS: none 683** 684** IMPLICIT OUTPUTS: none 685** 686** FUNCTION VALUE: void 687** 688** SIDE EFFECTS: none 689** 690**-- 691**/ 692 693PUBLIC void rpc_binding_copy 694( 695 rpc_binding_handle_t src_binding_h, 696 rpc_binding_handle_t *dst_binding_h, 697 unsigned32 *status 698) 699{ 700 rpc_binding_rep_p_t src_binding_rep = (rpc_binding_rep_p_t) src_binding_h; 701 rpc_binding_rep_p_t dst_binding_rep; 702 rpc_addr_p_t rpc_addr; 703 unsigned32 tmp_status; 704 boolean have_addr = false; 705 rpc_cs_method_eval_p_t method_s_p; 706 rpc_cs_method_eval_p_t method_d_p; 707 rpc_cs_tags_eval_p_t tags_s_p; 708 rpc_cs_tags_eval_p_t tags_d_p; 709 710 if (src_binding_rep == NULL) 711 { 712 *status = rpc_s_invalid_arg; 713 return; 714 } 715 716 CODING_ERROR (status); 717 RPC_VERIFY_INIT (); 718 719 RPC_BINDING_VALIDATE_CLIENT(src_binding_rep, status); 720 if (*status != rpc_s_ok) 721 return; 722 723 if (src_binding_rep->rpc_addr == NULL) 724 { 725 *status = rpc_s_invalid_arg; 726 return; 727 } 728 729 (*rpc_g_naf_id[src_binding_rep->rpc_addr->sa.family].epv 730 ->naf_addr_copy) 731 (src_binding_rep->rpc_addr, &rpc_addr, status); 732 if (*status != rpc_s_ok) return; 733 734 have_addr = true; 735 736 /* 737 * allocate a binding rep to hold the copy and init it from the source 738 */ 739 dst_binding_rep = rpc__binding_alloc ( 740 (boolean)src_binding_rep->is_server, &src_binding_rep->obj, 741 src_binding_rep->protocol_id, rpc_addr, status); 742 if (*status != rpc_s_ok) goto CLEANUP; 743 744 /* 745 * copy other common parts of the binding rep from the source to dest 746 */ 747 dst_binding_rep->timeout = src_binding_rep->timeout; 748 dst_binding_rep->call_timeout_time = src_binding_rep->call_timeout_time; 749 dst_binding_rep->addr_is_dynamic = src_binding_rep->addr_is_dynamic; 750 dst_binding_rep->bound_server_instance 751 = src_binding_rep->bound_server_instance; 752 dst_binding_rep->extended_bind_flag = src_binding_rep->extended_bind_flag; 753 754 /* 755 * Copy the auth info. 756 */ 757 if (src_binding_rep->auth_info != NULL) 758 { 759 rpc__auth_info_reference (src_binding_rep->auth_info); 760 dst_binding_rep->auth_info = src_binding_rep->auth_info; 761 } 762 763 /* 764 * Copy transport information 765 */ 766 767 if (src_binding_rep->transport_info != NULL) 768 { 769 rpc__transport_info_retain(src_binding_rep->transport_info); 770 dst_binding_rep->transport_info = src_binding_rep->transport_info; 771 } 772 773 /* 774 * Copy the protocol version 775 */ 776 if (src_binding_rep->protocol_version != NULL) 777 { 778 rpc__binding_prot_version_alloc( 779 &(dst_binding_rep->protocol_version), 780 src_binding_rep->protocol_version->major_version, 781 src_binding_rep->protocol_version->minor_version, 782 status); 783 if (*status != rpc_s_ok) goto CLEANUP; 784 } 785 786 /* 787 * Copy the ns_specific. 788 */ 789 if (src_binding_rep->ns_specific != NULL) 790 { 791 /* NOTE 792 * This needs to be replaced with the real copy. 793 * For now set the field to NULL so later we don't improperly 794 * try to free the field. 795 * 796 * When we get around to doing this, see how this field is 797 * freed in rpc_binding_free for a hint on doing this. 798 * You'll probably need to add a similar entry point in nsinit.c 799 */ 800 dst_binding_rep->ns_specific = NULL; 801 } 802 803 /* 804 * Copy the extended code set i14y information 805 */ 806 if (src_binding_rep->extended_bind_flag == RPC_C_BH_EXTENDED_CODESETS) 807 { 808 /* Copy codesets relating binding information. 809 * Determine the data structure 810 */ 811 switch (src_binding_rep->cs_eval.key) 812 { 813 case RPC_CS_EVAL_METHOD: 814 method_s_p = &src_binding_rep->cs_eval.tagged_union.method_key; 815 method_d_p = &dst_binding_rep->cs_eval.tagged_union.method_key; 816 817 dst_binding_rep->cs_eval.key = src_binding_rep->cs_eval.key; 818 method_d_p->method = method_s_p->method; 819 method_d_p->tags.stag = method_s_p->tags.stag; 820 method_d_p->tags.drtag = method_s_p->tags.drtag; 821 method_d_p->tags.stag_max_bytes 822 = method_s_p->tags.stag_max_bytes; 823 method_d_p->tags.client_tag = method_s_p->tags.client_tag; 824 method_d_p->tags.client_max_bytes 825 = method_s_p->tags.client_max_bytes; 826 method_d_p->tags.type_handle = method_d_p->tags.type_handle; 827 method_d_p->fixed = method_s_p->fixed; 828 method_d_p->cs_stub_eval_func = method_s_p->cs_stub_eval_func; 829 830 method_s_p->server = NULL; 831 method_d_p->client = NULL; 832 833 break; 834 835 case RPC_CS_EVAL_TAGS: 836 tags_s_p = &src_binding_rep->cs_eval.tagged_union.tags_key; 837 tags_d_p = &dst_binding_rep->cs_eval.tagged_union.tags_key; 838 839 dst_binding_rep->cs_eval.key = src_binding_rep->cs_eval.key; 840 tags_d_p->stag = tags_s_p->stag; 841 tags_d_p->drtag = tags_s_p->drtag; 842 tags_d_p->stag_max_bytes = tags_s_p->stag_max_bytes; 843 tags_d_p->client_tag = tags_s_p->client_tag; 844 tags_d_p->client_max_bytes = tags_s_p->client_max_bytes; 845 tags_d_p->type_handle = tags_d_p->type_handle; 846 847 break; 848 849 default: 850 *status = rpc_s_ss_invalid_codeset_tag; 851 break; 852 } 853 } 854 855 /* 856 * return the destination binding rep as a binding handle 857 */ 858 *dst_binding_h = (rpc_binding_handle_t) dst_binding_rep; 859 860 /* 861 * let the protocol service copy any stuff it wants to 862 */ 863 (*rpc_g_protocol_id[src_binding_rep->protocol_id].binding_epv 864 ->binding_copy) (src_binding_rep, dst_binding_rep, status); 865 866CLEANUP: 867 868 if (*status != rpc_s_ok && have_addr) 869 rpc__naf_addr_free (&rpc_addr, &tmp_status); 870} 871 872/* 873**++ 874** 875** ROUTINE NAME: rpc_binding_to_string_binding 876** 877** SCOPE: PUBLIC - declared in rpc.idl 878** 879** DESCRIPTION: 880** 881** This routine will convert a Binding Rep data structure to its string 882** represenation, which is called a "string binding". It will first convert 883** the object UUID contained in the Binding Rep to string format. The string 884** format of the Protocol Sequence ID contained in the RPC Address will be 885** looked up in the RPC Protocol Sequence ID table. It will the call the 886** appropriate Network Address Family Extension Service to return the 887** endpoint, network address and network options form the RPC Address in the 888** Binding Rep. 889** 890** INPUTS: 891** 892** binding_h The binding handle which points to the binding 893** rep data structure to be converted. 894** 895** INPUTS/OUTPUTS: none 896** 897** OUTPUTS: 898** 899** string_binding A string representation of the binding rep data 900** structure. 901** 902** status A value indicating the status of the routine. 903** 904** rpc_s_ok The call was successful. 905** rpc_s_invalid_binding 906** RPC Protocol ID in binding handle was invalid. 907** rpc_s_coding_error 908** 909** IMPLICIT INPUTS: none 910** 911** IMPLICIT OUTPUTS: none 912** 913** FUNCTION VALUE: void 914** 915** SIDE EFFECTS: none 916** 917**-- 918**/ 919 920PUBLIC void rpc_binding_to_string_binding 921( 922 rpc_binding_handle_t binding_h, 923 unsigned_char_p_t *string_binding, 924 unsigned32 *status 925) 926{ 927 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 928 rpc_addr_p_t rpc_addr = NULL; 929 unsigned_char_p_t object_uuid = NULL; 930 unsigned_char_p_t endpoint = NULL; 931 unsigned_char_p_t netaddr = NULL; 932 unsigned_char_p_t network_options = NULL; 933 unsigned32 temp_status; 934 935 assert(binding_rep != NULL); 936 937 CODING_ERROR (status); 938 RPC_VERIFY_INIT (); 939 940 /* 941 * if the output argument is NULL, don't do anything 942 */ 943 if (string_binding == NULL) 944 { 945 *status = rpc_s_ok; 946 return; 947 } 948 949 RPC_BINDING_VALIDATE(binding_rep, status); 950 if (*status != rpc_s_ok) 951 return; 952 953 /* 954 * convert the object UUID in the binding rep to string format 955 * (if it is non-nil - otherwise, keep it as a NULL pointer) 956 */ 957 if (!uuid_is_nil (&(binding_rep->obj), status)) 958 { 959 uuid_to_string (&(binding_rep->obj), &object_uuid, status); 960 961 if (*status != uuid_s_ok) 962 { 963 goto CLEANUP; 964 } 965 } 966 967 /* 968 * if the RPC address in the binding is NULL, get one from protocol service 969 */ 970 if (binding_rep->rpc_addr == NULL) 971 { 972 973 /* 974 * get the RPC address from the protocol service 975 */ 976 (*rpc_g_protocol_id[binding_rep->protocol_id].binding_epv 977 ->binding_inq_addr) (binding_rep, &rpc_addr, status); 978 979 if (*status != rpc_s_ok) 980 { 981 goto CLEANUP; 982 } 983 } 984 else 985 { 986 /* 987 * otherwise use the RPC address in the binding rep 988 */ 989 rpc_addr = binding_rep->rpc_addr; 990 } 991 992 /* 993 * get the endpoint from the network address family extension 994 */ 995 (*rpc_g_naf_id[rpc_addr->sa.family].epv->naf_addr_inq_endpoint) 996 (rpc_addr, &endpoint, status); 997 998 if (*status != rpc_s_ok) 999 { 1000 goto CLEANUP; 1001 } 1002 1003 /* 1004 * get the network address from the network address family extension 1005 */ 1006 (*rpc_g_naf_id[rpc_addr->sa.family].epv->naf_addr_inq_netaddr) 1007 (rpc_addr, &netaddr, status); 1008 1009 if (*status != rpc_s_ok) 1010 { 1011 goto CLEANUP; 1012 } 1013 1014 /* 1015 * get the network options from the network address family extension 1016 */ 1017 (*rpc_g_naf_id[rpc_addr->sa.family].epv->naf_addr_inq_options) 1018 (rpc_addr, &network_options, status); 1019 1020 if (*status != rpc_s_ok) 1021 { 1022 goto CLEANUP; 1023 } 1024 1025 /* 1026 * got everything - now build the whole string 1027 * (note: if the object uuid was nil, a NULL will be passed here, 1028 * and it won't appear in the string binding; also note, we'll 1029 * return at this point with the status of rpc_string_binding_compose) 1030 */ 1031 rpc_string_binding_compose ( 1032 object_uuid, rpc_g_protseq_id[rpc_addr->rpc_protseq_id].rpc_protseq, 1033 netaddr, endpoint, network_options, string_binding, status); 1034 1035CLEANUP: 1036 1037 /* 1038 * if anything failed along the way, or we got here succesfully, 1039 * cleanup local buffers and return with the last meaningful status 1040 */ 1041 if (object_uuid != NULL) 1042 { 1043 rpc_string_free (&object_uuid, &temp_status); 1044 } 1045 1046 if (endpoint != NULL) 1047 { 1048 rpc_string_free (&endpoint, &temp_status); 1049 } 1050 1051 if (netaddr != NULL) 1052 { 1053 rpc_string_free (&netaddr, &temp_status); 1054 } 1055 1056 if (network_options != NULL) 1057 { 1058 rpc_string_free (&network_options, &temp_status); 1059 } 1060} 1061 1062/* 1063**++ 1064** 1065** ROUTINE NAME: rpc_binding_from_string_binding 1066** 1067** SCOPE: PUBLIC - declared in rpc.idl 1068** 1069** DESCRIPTION: 1070** 1071** This routine converts a string binding to a Binding Rep data structure. 1072** It will strip the object UUID, RPC Protocol Sequence string, endpoint, 1073** network address and network options out of the string binding provided. 1074** A Binding Rep will then be allocated through the RPC Protocol Service 1075** identified in the RPC Protocol Sequence. An RPC Address will be allocated 1076** through the Network Address Family Extension Service identified in the 1077** RPC Protocol Sequence. The common fields of the Binding Rep will be set 1078** to defaults and the RPC Prtotcol Service will be called to initialize 1079** the RPC Protocol Service-specific part of the Binding Rep. 1080** 1081** 1082** If the string binding contains an endpoint, the addr_is_dynamic field 1083** in the binding rep is set to false, indicating a well-known endpoint. 1084** (This field is initialized to true in rpc__binding_alloc.) 1085** 1086** INPUTS: 1087** 1088** string_binding A string representation of the binding rep data 1089** structure. 1090** 1091** INPUTS/OUTPUTS: none 1092** 1093** OUTPUTS: 1094** 1095** binding_h The binding handle which points to the binding 1096** rep data structure to be created. 1097** 1098** status A value indicating the status of the routine. 1099** 1100** rpc_s_ok The call was successful. 1101** uuid_s_invalid_string_uuid 1102** Object UUID in string binding was invalid. 1103** rpc_s_invalid_string_binding 1104** String binding was invalid. 1105** rpc_s_coding_error 1106** 1107** IMPLICIT INPUTS: none 1108** 1109** IMPLICIT OUTPUTS: none 1110** 1111** FUNCTION VALUE: void 1112** 1113** SIDE EFFECTS: none 1114** 1115**-- 1116**/ 1117 1118PUBLIC void rpc_binding_from_string_binding 1119( 1120 unsigned_char_p_t string_binding, 1121 rpc_binding_handle_t *binding_h, 1122 unsigned32 *status 1123) 1124{ 1125 rpc_binding_rep_p_t binding_rep; 1126 idl_uuid_t obj_uuid; 1127 rpc_addr_p_t rpc_addr = NULL; 1128 unsigned_char_p_t string_object_uuid = NULL; 1129 unsigned_char_p_t protseq = NULL; 1130 unsigned_char_p_t endpoint = NULL; 1131 unsigned_char_p_t netaddr = NULL; 1132 unsigned_char_p_t network_options = NULL; 1133 rpc_protseq_id_t protseq_id; 1134 rpc_protocol_id_t protocol_id; 1135 rpc_naf_id_t naf_id = 0; 1136 unsigned32 temp_status; 1137 1138 CODING_ERROR (status); 1139 RPC_VERIFY_INIT (); 1140 1141 /* 1142 * extract the various fields from the string binding 1143 */ 1144 rpc_string_binding_parse (string_binding, &string_object_uuid, 1145 &protseq, &netaddr, &endpoint, &network_options, status); 1146 1147 if (*status != rpc_s_ok) 1148 { 1149 goto CLEANUP; 1150 } 1151 1152 /* 1153 * Convert the protocol sequence string to and protseq ID. 1154 */ 1155 protseq_id = rpc__network_pseq_id_from_pseq (protseq, status); 1156 1157 if (*status != rpc_s_ok) 1158 { 1159 goto CLEANUP; 1160 } 1161 1162 if (rpc_g_protseq_id[protseq_id].supported == false) 1163 { 1164 *status = rpc_s_protseq_not_supported; 1165 goto CLEANUP; 1166 } 1167 1168 protocol_id = rpc_g_protseq_id[protseq_id].rpc_protocol_id; 1169 naf_id = rpc_g_protseq_id[protseq_id].naf_id; 1170 1171 /* 1172 * set the object UUID to the one given in the string 1173 * - if the string is empty, none was given - use the nil uuid 1174 */ 1175 if (*string_object_uuid != '\0') 1176 { 1177 uuid_from_string (string_object_uuid, &obj_uuid, status); 1178 } 1179 else 1180 { 1181 uuid_create_nil (&obj_uuid, status); 1182 } 1183 1184 if (*status != uuid_s_ok) 1185 { 1186 goto CLEANUP; 1187 } 1188 1189 /* 1190 * A NULL network address means to bind to the local host. 1191 * Otherwise, get an RPC address from the Network Address Family 1192 * Extension Service. 1193 */ 1194 if (*netaddr == '\0') 1195 { 1196 rpc__network_inq_local_addr (protseq_id, endpoint, &rpc_addr, status); 1197 } 1198 else 1199 { 1200 (*rpc_g_naf_id[naf_id].epv->naf_addr_alloc) 1201 (protseq_id, naf_id, endpoint, netaddr, network_options, 1202 &rpc_addr, status); 1203 } 1204 1205 if (*status != rpc_s_ok) 1206 { 1207 rpc_addr = NULL; 1208 goto CLEANUP; 1209 } 1210 1211 /* 1212 * allocate a binding rep and initialize it 1213 */ 1214 binding_rep = rpc__binding_alloc 1215 ((boolean)false, &obj_uuid, protocol_id, rpc_addr, status); 1216 1217 if (*status != rpc_s_ok) goto CLEANUP; 1218 1219 /* 1220 * A non-NULL endpoint means that the endpoint is well-known, so set 1221 * the addr_is_dynamic field to false. 1222 */ 1223 if (*endpoint != '\0') 1224 { 1225 binding_rep->addr_is_dynamic = false; 1226 } 1227 1228 /* 1229 * cast the binding handle to a binding rep pointer 1230 */ 1231 *binding_h = (rpc_binding_handle_t) binding_rep; 1232 1233 *status = rpc_s_ok; 1234 1235CLEANUP: 1236 1237 if (string_object_uuid != NULL) 1238 { 1239 rpc_string_free (&string_object_uuid, &temp_status); 1240 } 1241 1242 if (protseq != NULL) 1243 { 1244 rpc_string_free (&protseq, &temp_status); 1245 } 1246 1247 if (endpoint != NULL) 1248 { 1249 rpc_string_free (&endpoint, &temp_status); 1250 } 1251 1252 if (netaddr != NULL) 1253 { 1254 rpc_string_free (&netaddr, &temp_status); 1255 } 1256 1257 if (network_options != NULL) 1258 { 1259 rpc_string_free (&network_options, &temp_status); 1260 } 1261 1262 if (*status != rpc_s_ok) 1263 { 1264 unsigned32 tstatus; 1265 1266 if (rpc_addr != NULL) 1267 { 1268 (*rpc_g_naf_id[naf_id].epv->naf_addr_free) (&rpc_addr, &tstatus); 1269 } 1270 1271 if (*status == rpc_s_invalid_binding) 1272 { 1273 *status = rpc_s_invalid_string_binding; 1274 } 1275 1276 *binding_h = NULL; 1277 } 1278} 1279 1280 1281PRIVATE void rpc__string_netaddr_escape 1282( 1283 unsigned_char_p_t netaddr, 1284 unsigned_char_p_t *escaped_netaddr, 1285 unsigned32 *status 1286) 1287{ 1288 unsigned_char_p_t saved_netaddr; 1289 unsigned_char_p_t escaped_netaddr_ptr; 1290 size_t escaped_string_size = 1; /* include null at end */ 1291 1292 CODING_ERROR (status); 1293 1294 /* 1295 * if the output argument is NULL, don't do anything 1296 */ 1297 if (escaped_netaddr == NULL) 1298 { 1299 *status = rpc_s_ok; 1300 return; 1301 } 1302 1303 /* 1304 * if the input argument is NULL, return NULL 1305 */ 1306 if (netaddr == NULL) 1307 { 1308 *escaped_netaddr = NULL; 1309 *status = rpc_s_ok; 1310 return; 1311 } 1312 1313 /* 1314 * calculate total size of the string including escaped out chars 1315 */ 1316 saved_netaddr = netaddr; 1317 while (*netaddr != '\0') 1318 { 1319 switch (*netaddr) 1320 { 1321 case ' ': 1322 case '@': 1323 case ':': 1324 case '[': 1325 case ']': 1326 case ',': 1327 case '\\': 1328 /* have to add one more char due to adding '\' */ 1329 escaped_string_size += 2; 1330 break; 1331 1332 default: 1333 escaped_string_size += 1; 1334 break; 1335 } 1336 netaddr++; 1337 } 1338 1339 /* 1340 * heap allocate storage for the escaped string 1341 */ 1342 RPC_MEM_ALLOC (*escaped_netaddr, 1343 unsigned_char_p_t, 1344 escaped_string_size, 1345 RPC_C_MEM_STRING, 1346 RPC_C_MEM_WAITOK); 1347 1348 escaped_netaddr_ptr = *escaped_netaddr; 1349 1350 /* make sure string ends in null */ 1351 memset(escaped_netaddr_ptr, 0, escaped_string_size); 1352 1353 /* 1354 * copy chars and escape as needed 1355 */ 1356 netaddr = saved_netaddr; 1357 while (*netaddr != '\0') 1358 { 1359 switch (*netaddr) 1360 { 1361 case ' ': 1362 case '@': 1363 case ':': 1364 case '[': 1365 case ']': 1366 case ',': 1367 case '\\': 1368 /* add escape char of '\' followed by the char */ 1369 *(escaped_netaddr_ptr++) = '\\'; 1370 *(escaped_netaddr_ptr++) = *(netaddr++); 1371 break; 1372 1373 default: 1374 /* no need to escape, just copy the char */ 1375 *(escaped_netaddr_ptr++) = *(netaddr++); 1376 break; 1377 } 1378 } 1379 1380 *status = rpc_s_ok; 1381 return; 1382} 1383 1384 1385PRIVATE void rpc__string_netaddr_unescape 1386( 1387 unsigned_char_p_t escaped_netaddr, 1388 unsigned_char_p_t *netaddr, 1389 unsigned32 *status 1390) 1391{ 1392 unsigned_char_p_t netaddr_ptr; 1393 size_t escaped_string_size; 1394 unsigned_char_p_t p1, p2; 1395 1396 CODING_ERROR (status); 1397 1398 /* 1399 * if the output argument is NULL, don't do anything 1400 */ 1401 if (netaddr == NULL) 1402 { 1403 *status = rpc_s_ok; 1404 return; 1405 } 1406 1407 /* 1408 * if the input argument is NULL, return NULL 1409 */ 1410 if (escaped_netaddr == NULL) 1411 { 1412 *netaddr = NULL; 1413 *status = rpc_s_ok; 1414 return; 1415 } 1416 1417 /* 1418 * The unescaped string will be the same length or shorter than 1419 * the escaped string so allocate same size as the escaped string. 1420 */ 1421 escaped_string_size = strlen ((char*) escaped_netaddr); 1422 1423 /* 1424 * heap allocate storage for the unescaped string 1425 */ 1426 RPC_MEM_ALLOC (*netaddr, 1427 unsigned_char_p_t, 1428 escaped_string_size + 1, 1429 RPC_C_MEM_STRING, 1430 RPC_C_MEM_WAITOK); 1431 1432 netaddr_ptr = *netaddr; 1433 1434 /* make sure string ends in null */ 1435 memset(netaddr_ptr, 0, escaped_string_size + 1); 1436 1437 /* 1438 * copy the string, filtering out escape chars 1439 */ 1440 p2 = netaddr_ptr; 1441 p1 = escaped_netaddr; 1442 1443 while (*p1 != '\0') 1444 { 1445 switch (*p1) 1446 { 1447 case '\\': 1448 /* skip escape char of '\' and just copy the char */ 1449 if (p1[1] != '\0') { 1450 p1++; 1451 *(p2++) = *(p1++); 1452 } 1453 else { 1454 /* must be at end of escaped string so just copy the '\' */ 1455 *(p2++) = *(p1++); 1456 } 1457 break; 1458 1459 default: 1460 /* no need to unescape, just copy the char */ 1461 *(p2++) = *(p1++); 1462 break; 1463 } 1464 } 1465 1466 *status = rpc_s_ok; 1467 return; 1468} 1469 1470 1471/* 1472**++ 1473** 1474** ROUTINE NAME: rpc_string_binding_parse 1475** 1476** SCOPE: PUBLIC - declared in rpc.idl 1477** 1478** DESCRIPTION: 1479** 1480** This routine will split the string binding provided into multiple 1481** components. 1482** 1483** INPUTS: 1484** 1485** string_binding A string representation of the binding rep data 1486** structure. 1487** 1488** INPUTS/OUTPUTS: none 1489** 1490** OUTPUTS: 1491** 1492** string_obj_uuid A string representation of an object UUID. 1493** 1494** protseq An RPC Protocol Sequence. 1495** 1496** netaddr A Network Address. 1497** 1498** endpoint An RPC Endpoint. 1499** 1500** network_options A string of Network Options. 1501** 1502** status A value indicating the status of the routine. 1503** 1504** rpc_s_ok The call was successful. 1505** rpc_s_invalid_string_binding 1506** The string binding could not be parsed 1507** rpc_s_coding_error 1508** 1509** IMPLICIT INPUTS: none 1510** 1511** IMPLICIT OUTPUTS: none 1512** 1513** FUNCTION VALUE: void 1514** 1515** SIDE EFFECTS: none 1516** 1517**-- 1518**/ 1519 1520PUBLIC void rpc_string_binding_parse 1521( 1522 unsigned_char_p_t string_binding, 1523 unsigned_char_p_t *string_object_uuid, 1524 unsigned_char_p_t *protseq, 1525 unsigned_char_p_t *netaddr, 1526 unsigned_char_p_t *endpoint, 1527 unsigned_char_p_t *network_options, 1528 unsigned32 *status 1529) 1530{ 1531#define RPC_C_NETWORK_OPTIONS_MAX 1024 1532 1533 unsigned_char_p_t binding_ptr; 1534 unsigned_char_p_t option_ptr = NULL; 1535 size_t count; 1536 boolean get_endpoint; 1537 unsigned32 temp_status; 1538 size_t len; 1539 unsigned_char_p_t escaped_netaddr; 1540 1541 CODING_ERROR (status); 1542 RPC_VERIFY_INIT (); 1543 1544 /* 1545 * make sure we have something to start with 1546 */ 1547 if (string_binding == NULL) 1548 { 1549 *status = rpc_s_invalid_string_binding; 1550 return; 1551 } 1552 1553 /* 1554 * Initialize netaddr, endpoint and network_options if pointers are non-NULL 1555 */ 1556 if (netaddr != NULL) 1557 { 1558 *netaddr = NULL; 1559 } 1560 if (endpoint != NULL) 1561 { 1562 *endpoint = NULL; 1563 } 1564 if (network_options != NULL) 1565 { 1566 *network_options = NULL; 1567 } 1568 1569 binding_ptr = string_binding; 1570 1571 /* 1572 * get in the object UUID and protocol sequence 1573 */ 1574 count = rpc__strcspn (binding_ptr, "@"); 1575 if (string_object_uuid != NULL) 1576 { 1577 { 1578 RPC_MEM_ALLOC ( 1579 *string_object_uuid, 1580 unsigned_char_p_t, 1581 count + 1, 1582 RPC_C_MEM_STRING, 1583 RPC_C_MEM_WAITOK); 1584 1585 if (count > 0) 1586 { 1587 rpc__strncpy (*string_object_uuid, binding_ptr, count - 1); 1588 } 1589 else 1590 { 1591 **string_object_uuid = '\0'; 1592 } 1593 } 1594 } 1595 /* 1596 * In any case, advance the pointer. 1597 */ 1598 binding_ptr += count; 1599 1600 count = rpc__strcspn (binding_ptr, ":"); 1601 if (protseq != NULL) 1602 { 1603 { 1604 RPC_MEM_ALLOC ( 1605 *protseq, 1606 unsigned_char_p_t, 1607 count + 1, 1608 RPC_C_MEM_STRING, 1609 RPC_C_MEM_WAITOK); 1610 1611 if (count > 0) 1612 { 1613 rpc__strncpy (*protseq, binding_ptr, count - 1); 1614 } 1615 else 1616 { 1617 **protseq = '\0'; 1618 } 1619 } 1620 } 1621 /* 1622 * In any case, advance the pointer. 1623 */ 1624 binding_ptr += count; 1625 1626 /* 1627 * see if there are options after the network address 1628 */ 1629 if ((count = rpc__strcspn (binding_ptr, "[")) == 0) 1630 { 1631 /* 1632 * if there was no '[' terminator, maybe there are no options - 1633 * but there still might be a network address - go for it! 1634 */ 1635 if (netaddr != NULL) 1636 { 1637 len = strlen ((char *) binding_ptr); 1638 RPC_MEM_ALLOC ( 1639 *netaddr, 1640 unsigned_char_p_t, 1641 len + 1, 1642 RPC_C_MEM_STRING, 1643 RPC_C_MEM_WAITOK); 1644 1645 /* 1646 * Note: we are counting on null termination here, even if len == 0 1647 */ 1648 rpc__strncpy (*netaddr, binding_ptr, len); 1649 } 1650 } 1651 else 1652 { 1653 /* 1654 * if there are options, first get the network address 1655 */ 1656 if (netaddr != NULL) 1657 { 1658 RPC_MEM_ALLOC ( 1659 *netaddr, 1660 unsigned_char_p_t, 1661 count, 1662 RPC_C_MEM_STRING, 1663 RPC_C_MEM_WAITOK); 1664 1665 rpc__strncpy (*netaddr, binding_ptr, count - 1); 1666 } 1667 binding_ptr += count; 1668 1669 /* 1670 * then get the entries in the options list one by one 1671 */ 1672 if (network_options != NULL) 1673 { 1674 /* 1675 * we've got to allocate enough space to catch all of the 1676 * network options that might conceivably be here - a lot 1677 * will probably be wasted, but we have no way of knowing at 1678 * this time exactly how much, but we know it can be no more than 1679 * the length of what remains of this string binding. 1680 */ 1681 1682 /* 1683 * Allocate one byte more than we need to cover bug - 1684 * see modification history for 21-may-91. 1685 */ 1686 RPC_MEM_ALLOC ( 1687 *network_options, 1688 unsigned_char_p_t, 1689 strlen ((char *)binding_ptr) + 1, 1690 RPC_C_MEM_STRING, 1691 RPC_C_MEM_WAITOK); 1692 1693 option_ptr = *network_options; 1694 *option_ptr = '\0'; 1695 } 1696 1697 while ((count > 0) && (*binding_ptr != '\0')) 1698 { 1699 get_endpoint = false; 1700 1701 /* 1702 * first see if there's an option tag 1703 */ 1704 count = rpc__strcspn (binding_ptr, "=,"); 1705 1706 if (count == 0 || *(binding_ptr + count - 1) != '=') 1707 { 1708 /* 1709 * if there's no option tag, this must be an endpoint 1710 */ 1711 get_endpoint = true; 1712 } 1713 else 1714 { 1715 /* 1716 * see if the tag is an endpoint specifier - 1717 * but skip over any leading white space 1718 */ 1719 for (; (*binding_ptr == ' ' || *binding_ptr == '\t') && 1720 *binding_ptr != '\0'; binding_ptr++, count--); 1721 1722 if ((strncmp ((char *) binding_ptr, "endpoint", (count-1))) 1723 == 0) 1724 { 1725 /* 1726 * if the tag was "endpoint", skip to the equal sign 1727 */ 1728 get_endpoint = true; 1729 binding_ptr += count; 1730 } 1731 } 1732 1733 /* 1734 * if this is an endpoint, collect it 1735 */ 1736 if (get_endpoint && endpoint != NULL) 1737 { 1738 size_t token_end; 1739 /* 1740 * We want to return an error if there is more than one 1741 * endpoint specified (this will also catch an endpoint 1742 * specified with extra brackets, like "[[foo]]" as a side 1743 * effect). 1744 */ 1745 if (*endpoint != NULL) 1746 { 1747 *status = rpc_s_invalid_string_binding; 1748 goto CLEANUP; 1749 } 1750 1751 token_end = rpc__get_token(binding_ptr, '\\', ",]", 1752 endpoint, status); 1753 1754 if(*status != rpc_s_ok) 1755 goto CLEANUP; 1756 1757 /* 1758 * We want to return an error if there is no closing ']'; 1759 */ 1760 if (binding_ptr[token_end] == '\0') 1761 { 1762 *status = rpc_s_invalid_string_binding; 1763 goto CLEANUP; 1764 } 1765 1766 binding_ptr += token_end + 1; 1767 } 1768 else if (get_endpoint && endpoint == NULL) 1769 /* 1770 * Skip over the endpoint 1771 */ 1772 { 1773 size_t token_end = rpc__get_token(binding_ptr, '\\', ",]", 1774 NULL, status); 1775 binding_ptr += token_end + 1; 1776 } 1777 else 1778 { 1779 count = rpc__strcspn (binding_ptr, ",]"); 1780 /* 1781 * If this is the last token, make sure the string is properly terminated. 1782 */ 1783 if ((count == 0) && ((strlen ((char *) binding_ptr)) != 0)) 1784 { 1785 *status = rpc_s_invalid_string_binding; 1786 goto CLEANUP; 1787 } 1788 1789 /* 1790 * if not an endpoint, collect the option tag and value 1791 */ 1792 if (network_options != NULL) 1793 { 1794 /* 1795 * We can have any number of network options, but we'll 1796 * lose the last one if the string doesn't have a 1797 * terminator. 1798 * (this code is probably redundant, now) 1799 */ 1800 if (count == 0) 1801 { 1802 *status = rpc_s_invalid_string_binding; 1803 goto CLEANUP; 1804 } 1805 1806 rpc__strncpy (option_ptr, binding_ptr, count); 1807 option_ptr += count; 1808 } 1809 1810 /* 1811 * advance to the next token in the string. 1812 */ 1813 binding_ptr += count; 1814 } 1815 } 1816 } 1817 1818 /* 1819 * if component strings were created, compress white space out of the 1820 * results - otherwise, return empty strings for things that were wanted 1821 * but not found 1822 */ 1823 if (string_object_uuid != NULL) 1824 { 1825 if (*string_object_uuid != NULL) 1826 { 1827 rpc__strsqz (*string_object_uuid); 1828 } 1829 else 1830 { 1831 RPC_MEM_ALLOC ( 1832 *string_object_uuid, 1833 unsigned_char_p_t, 1834 1, 1835 RPC_C_MEM_STRING, 1836 RPC_C_MEM_WAITOK); 1837 1838 **string_object_uuid = '\0'; 1839 } 1840 } 1841 1842 if (protseq != NULL) 1843 { 1844 if (*protseq != NULL) 1845 { 1846 rpc__strsqz (*protseq); 1847 } 1848 else 1849 { 1850 RPC_MEM_ALLOC ( 1851 *protseq, 1852 unsigned_char_p_t, 1853 1, 1854 RPC_C_MEM_STRING, 1855 RPC_C_MEM_WAITOK); 1856 1857 **protseq = '\0'; 1858 } 1859 } 1860 1861 if (netaddr != NULL) 1862 { 1863 if (*netaddr != NULL) 1864 { 1865 /* 1866 * call rpc__strsqz before unescaping so that dont lose any escaped 1867 * spaces 1868 */ 1869 rpc__strsqz (*netaddr); 1870 1871 /* unescape the netaddr before returning it */ 1872 escaped_netaddr = *netaddr; 1873 rpc__string_netaddr_unescape(escaped_netaddr, netaddr, &temp_status); 1874 if (temp_status == rpc_s_ok) 1875 { 1876 /* free the escaped netaddr */ 1877 rpc_string_free (&escaped_netaddr, &temp_status); 1878 } 1879 else 1880 { 1881 /* error occurred so restore original netaddr */ 1882 *netaddr = escaped_netaddr; 1883 } 1884 } 1885 else 1886 { 1887 RPC_MEM_ALLOC ( 1888 *netaddr, 1889 unsigned_char_p_t, 1890 1, 1891 RPC_C_MEM_STRING, 1892 RPC_C_MEM_WAITOK); 1893 1894 **netaddr = '\0'; 1895 } 1896 } 1897 1898 if (endpoint != NULL) 1899 { 1900 if (*endpoint != NULL) 1901 { 1902 rpc__strsqz (*endpoint); 1903 } 1904 else 1905 { 1906 RPC_MEM_ALLOC ( 1907 *endpoint, 1908 unsigned_char_p_t, 1909 1, 1910 RPC_C_MEM_STRING, 1911 RPC_C_MEM_WAITOK); 1912 1913 **endpoint = '\0'; 1914 } 1915 } 1916 1917 if (network_options != NULL) 1918 { 1919 if (*network_options != NULL) 1920 { 1921 rpc__strsqz (*network_options); 1922 1923 /* 1924 * clip the trailing separator off the network options string 1925 * to be neat 1926 */ 1927 if ((count = strlen ((char *) *network_options)) > 0) 1928 { 1929 (*network_options)[count - 1] = '\0'; 1930 } 1931 } 1932 else 1933 { 1934 RPC_MEM_ALLOC ( 1935 *network_options, 1936 unsigned_char_p_t, 1937 1, 1938 RPC_C_MEM_STRING, 1939 RPC_C_MEM_WAITOK); 1940 1941 **network_options = '\0'; 1942 } 1943 } 1944 1945 *status = rpc_s_ok; 1946 return; 1947 1948CLEANUP: 1949 1950 /* 1951 * free any buffers that have been allocated 1952 */ 1953 if (string_object_uuid != NULL && *string_object_uuid != NULL) 1954 { 1955 rpc_string_free (string_object_uuid, &temp_status); 1956 } 1957 1958 if (protseq != NULL && *protseq != NULL) 1959 { 1960 rpc_string_free (protseq, &temp_status); 1961 } 1962 1963 if (netaddr != NULL && *netaddr != NULL) 1964 { 1965 rpc_string_free (netaddr, &temp_status); 1966 } 1967 1968 if (endpoint != NULL && *endpoint != NULL) 1969 { 1970 rpc_string_free (endpoint, &temp_status); 1971 } 1972 1973 if (network_options != NULL && *network_options != NULL) 1974 { 1975 rpc_string_free (network_options, &temp_status); 1976 } 1977 1978 return; 1979} 1980 1981/* 1982**++ 1983** 1984** ROUTINE NAME: rpc_string_binding_compose 1985** 1986** SCOPE: PUBLIC - declared in rpc.idl 1987** 1988** DESCRIPTION: 1989** 1990** This routine will combine the components of a string binding and 1991** return a formatted string binding. 1992** 1993** INPUTS: 1994** 1995** string_obj_uuid A string representation of an object UUID. 1996** 1997** protseq An RPC Protocol Sequence. 1998** 1999** netaddr A Network Address. 2000** 2001** endpoint An RPC Endpoint. 2002** 2003** network_options A string of Network Options. 2004** 2005** INPUTS/OUTPUTS: none 2006** 2007** OUTPUTS: 2008** 2009** string_binding A string representation of the binding rep data 2010** structure. 2011** 2012** status A value indicating the status of the routine. 2013** 2014** rpc_s_ok The call was successful. 2015** rpc_s_invalid_binding 2016** RPC Protocol ID in binding handle was invalid. 2017** rpc_s_coding_error 2018** 2019** IMPLICIT INPUTS: none 2020** 2021** IMPLICIT OUTPUTS: none 2022** 2023** FUNCTION VALUE: void 2024** 2025** SIDE EFFECTS: none 2026** 2027**-- 2028**/ 2029 2030PUBLIC void rpc_string_binding_compose 2031( 2032 unsigned_char_p_t string_object_uuid, 2033 unsigned_char_p_t protseq, 2034 unsigned_char_p_t netaddr, 2035 unsigned_char_p_t endpoint, 2036 unsigned_char_p_t network_options, 2037 unsigned_char_p_t *string_binding, 2038 unsigned32 *status 2039) 2040{ 2041 unsigned_char_p_t string_binding_ptr; 2042 unsigned32 string_binding_size = 1; 2043 unsigned_char_p_t escaped_netaddr = NULL; 2044 unsigned_char_p_t temp_netaddr = NULL; 2045 2046 CODING_ERROR (status); 2047 RPC_VERIFY_INIT (); 2048 2049 /* 2050 * if the output argument is NULL, don't do anything 2051 */ 2052 if (string_binding == NULL) 2053 { 2054 *status = rpc_s_ok; 2055 return; 2056 } 2057 2058 /* 2059 * calculate the total size of the resulting string binding - the sum 2060 * of the lengths of all the non-null input strings, plus space for 2061 * any delimiters that might possibly be needed (and the requisite 2062 * null terminator) 2063 */ 2064 if ((string_object_uuid != NULL) && (*string_object_uuid != '\0')) 2065 { 2066 string_binding_size += strlen ((char *) string_object_uuid) + 1; 2067 } 2068 2069 if (protseq != NULL) 2070 { 2071 string_binding_size += strlen ((char *) protseq) + 1; 2072 } 2073 2074 if (netaddr != NULL) 2075 { 2076 /* escape out the netaddr string */ 2077 rpc__string_netaddr_escape(netaddr, &escaped_netaddr, status); 2078 if (*status == rpc_s_ok) 2079 { 2080 /* add in the len of the escaped string */ 2081 string_binding_size += strlen ((char *) escaped_netaddr) + 1; 2082 } 2083 else 2084 { 2085 /* error occurred so add in the len of netaddr */ 2086 string_binding_size += strlen ((char *) netaddr) + 1; 2087 } 2088 2089 } 2090 2091 if (endpoint != NULL) 2092 { 2093 string_binding_size += strlen ((char *) endpoint) + 2; 2094 } 2095 2096 if (network_options != NULL) 2097 { 2098 string_binding_size += strlen ((char *) network_options) + 2; 2099 } 2100 2101 /* 2102 * heap allocate storage for the string binding 2103 */ 2104 RPC_MEM_ALLOC ( 2105 *string_binding, 2106 unsigned_char_p_t, 2107 string_binding_size, 2108 RPC_C_MEM_STRING, 2109 RPC_C_MEM_WAITOK); 2110 2111 string_binding_ptr = *string_binding; 2112 2113 /* 2114 * fill in the object UUID 2115 */ 2116 if ((string_object_uuid != NULL) && (*string_object_uuid != '\0')) 2117 { 2118 while (*string_object_uuid != '\0') 2119 { 2120 *(string_binding_ptr++) = *(string_object_uuid++); 2121 } 2122 2123 *(string_binding_ptr++) = '@'; 2124 } 2125 2126 /* 2127 * fill in the protocol sequence 2128 */ 2129 if (protseq != NULL) 2130 { 2131 while (*protseq != '\0') 2132 { 2133 *(string_binding_ptr++) = *(protseq++); 2134 } 2135 2136 *(string_binding_ptr++) = ':'; 2137 } 2138 2139 /* 2140 * fill in the network address 2141 */ 2142 if (escaped_netaddr != NULL) 2143 { 2144 temp_netaddr = escaped_netaddr; 2145 while (*temp_netaddr != '\0') 2146 { 2147 *(string_binding_ptr++) = *(temp_netaddr++); 2148 } 2149 rpc_string_free (&escaped_netaddr, status); 2150 } 2151 else 2152 { 2153 /* 2154 * maybe an error occurred when trying to escape the netaddr? 2155 * try to copy in the original netaddr 2156 */ 2157 if (netaddr != NULL) 2158 { 2159 while (*netaddr != '\0') 2160 { 2161 *(string_binding_ptr++) = *(netaddr++); 2162 } 2163 } 2164 } 2165 2166 if (endpoint != NULL || network_options != NULL) 2167 { 2168 *(string_binding_ptr++) = '['; 2169 2170 /* 2171 * fill in the endpoint 2172 */ 2173 if (endpoint != NULL) 2174 { 2175 while (*endpoint != '\0') 2176 { 2177 *(string_binding_ptr++) = *(endpoint++); 2178 } 2179 2180 if (network_options != NULL && *network_options != '\0') 2181 { 2182 *(string_binding_ptr++) = ','; 2183 } 2184 } 2185 2186 /* 2187 * fill in any other options that might be specified 2188 */ 2189 if (network_options != NULL) 2190 { 2191 while (*network_options != '\0') 2192 { 2193 *(string_binding_ptr++) = *(network_options++); 2194 } 2195 } 2196 2197 *(string_binding_ptr++) = ']'; 2198 } 2199 2200 /* 2201 * terminate the string 2202 */ 2203 *(string_binding_ptr) = '\0'; 2204 2205 *status = rpc_s_ok; 2206 return; 2207} 2208 2209/* 2210**++ 2211** 2212** ROUTINE NAME: rpc__binding_alloc 2213** 2214** SCOPE: PRIVATE - declared in combind.h 2215** 2216** DESCRIPTION: 2217** 2218** This routine will allocate the memory for a Binding Rep data structure 2219** through the RPC Protocol Service identified in the input arguments. 2220** All the common fields of the Binding Rep will be initialized using 2221** defaults and the input arguments to this routine. The RPC Protocol 2222** Service will then be called to initialize the RPC Protocol Service 2223** specific parts of the Binding Rep. 2224** 2225** INPUTS: 2226** 2227** is_server T => a server-side binding handle should be created 2228** 2229** object_uuid The unique identifier of an object to which an 2230** RPC may be made. 2231** 2232** protocol_id The identifier of an RPC Protocol Service through 2233** which an RPC may be made. Since this is an internal 2234** routine it assumes this has been checked by the 2235** caller to see if it is a valid identifier. 2236** 2237** rpc_addr The location of the remote half of the RPC. 2238** 2239** INPUTS/OUTPUTS: none 2240** 2241** OUTPUTS: 2242** 2243** status A value indicating the status of the routine. 2244** 2245** rpc_s_ok The call was successful. 2246** rpc_s_coding_error 2247** 2248** IMPLICIT INPUTS: none 2249** 2250** IMPLICIT OUTPUTS: none 2251** 2252** FUNCTION VALUE: 2253** 2254** binding_rep A Binding Rep data structure containing the object 2255** UUID of an RPC as well as the location of the remote 2256** half of the RPC. 2257** 2258** SIDE EFFECTS: none 2259** 2260**-- 2261**/ 2262 2263PRIVATE rpc_binding_rep_t *rpc__binding_alloc 2264( 2265 boolean32 is_server, 2266 uuid_p_t object_uuid, 2267 rpc_protocol_id_t protocol_id, 2268 rpc_addr_p_t rpc_addr, 2269 unsigned32 *status 2270) 2271{ 2272 rpc_binding_rep_p_t binding_rep; 2273 unsigned_char_p_t endpoint = NULL; 2274 unsigned32 temp_status; 2275 2276 CODING_ERROR (status); 2277 2278 /* 2279 * get protocol service to allocate an empty binding rep 2280 */ 2281 binding_rep = (*rpc_g_protocol_id[protocol_id].binding_epv 2282 ->binding_alloc) (is_server, status); 2283 2284 /* 2285 * Initialize the common part of the binding rep. 2286 */ 2287 binding_rep->is_server = is_server; 2288 binding_rep->protocol_id = protocol_id; 2289 binding_rep->obj = *object_uuid; 2290 binding_rep->timeout = rpc_c_binding_default_timeout; 2291 binding_rep->ns_specific = NULL; 2292 binding_rep->auth_info = NULL; 2293 binding_rep->transport_info = NULL; 2294 binding_rep->bound_server_instance = false; 2295 binding_rep->addr_has_endpoint = false; 2296 binding_rep->refcnt = 1; /* the reference we are returning */ 2297 binding_rep->calls_in_progress = 0; 2298 binding_rep->call_timeout_time = 0; 2299 binding_rep->fork_count = rpc_g_fork_count; 2300 binding_rep->protocol_version = NULL; 2301 binding_rep->extended_bind_flag = RPC_C_BH_EXTENDED_NONE; 2302 2303 /* 2304 * By default, created bindings are declared to have dynamic 2305 * addresses; *this* default state is important. Callers of 2306 * binding_alloc that know they're associating a non-dynamic 2307 * addr with the binding can change this state. 2308 */ 2309 binding_rep->addr_is_dynamic = true; 2310 2311 if (rpc_addr != NULL) 2312 { 2313 /* 2314 * find out if the RPC address contains an endpoint 2315 */ 2316 (*rpc_g_naf_id[rpc_addr->sa.family].epv->naf_addr_inq_endpoint) 2317 (rpc_addr, &endpoint, status); 2318 2319 /* 2320 * If the addr has an endpoint, tell everyone. 2321 */ 2322 if (*status != rpc_s_ok) 2323 { 2324 /* 2325 * then ask the protocol service to free the binding rep and 2326 * NULL the reference. 2327 */ 2328 (*rpc_g_protocol_id[protocol_id].binding_epv->binding_free) 2329 (&binding_rep, &temp_status); 2330 /* mdn 23.10.1999: FIXME if I am wrong 2331 * if endpoint was allocated it is not a NULL pointer, so 2332 * it must be freed. */ 2333 /* return (NULL); */ 2334 binding_rep = NULL; 2335 goto CLEANUP; 2336 } 2337 else 2338 { 2339 if (strlen ((char *) endpoint) != 0) 2340 { 2341 binding_rep->addr_has_endpoint = true; 2342 } 2343 } 2344 } 2345 2346 /* 2347 * set the pointer to the specified rpc address in the binding 2348 */ 2349 binding_rep->rpc_addr = rpc_addr; 2350 2351 /* 2352 * get the protocol service to initialize the rest of the binding 2353 */ 2354 (*rpc_g_protocol_id[protocol_id].binding_epv 2355 ->binding_init) (binding_rep, status); 2356 2357 *status = rpc_s_ok; 2358 2359CLEANUP: 2360 2361 if (endpoint != NULL) 2362 { 2363 rpc_string_free (&endpoint, &temp_status); 2364 } 2365 2366 return (binding_rep); 2367} 2368 2369/* 2370**++ 2371** 2372** ROUTINE NAME: rpc_binding_inq_client 2373** 2374** SCOPE: PUBLIC 2375** 2376** DESCRIPTION: 2377** 2378** This routine returns a protocol service dependent client handle which 2379** can be used by the stubs to identify a particular instance of a 2380** particular client process. 2381** 2382** INPUTS: 2383** 2384** binding_h Server stub binding handle 2385** 2386** INPUTS/OUTPUTS: none 2387** 2388** OUTPUTS: 2389** 2390** client_h Client handle for use with monitor_liveness routine 2391** 2392** status A value indicating the status of the routine. 2393** rpc_s_invalid_binding 2394** RPC Protocol ID in binding handle was invalid. 2395** 2396** 2397** 2398** IMPLICIT INPUTS: none 2399** 2400** IMPLICIT OUTPUTS: none 2401** 2402** FUNCTION VALUE: 2403** 2404** void 2405** 2406** SIDE EFFECTS: none 2407** 2408**-- 2409**/ 2410 2411PUBLIC void rpc_binding_inq_client 2412( 2413 rpc_binding_handle_t binding_h, 2414 rpc_client_handle_t *client_h, 2415 unsigned32 *status 2416) 2417{ 2418 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 2419 2420 assert(binding_rep != NULL); 2421 2422 CODING_ERROR (status); 2423 RPC_VERIFY_INIT (); 2424 2425 RPC_BINDING_VALIDATE_SERVER(binding_rep, status); 2426 if (*status != rpc_s_ok) 2427 return; 2428 2429 /* 2430 * Ask the protocol service for a client handle associated with 2431 * the client on the other end of the connection specified by this 2432 * server binding handle. 2433 */ 2434 (*rpc_g_protocol_id[binding_rep->protocol_id].binding_epv 2435 ->binding_inq_client) (binding_rep, client_h, status); 2436} 2437 2438/* 2439**++ 2440** 2441** ROUTINE NAME: rpc_binding_handle_copy 2442** 2443** SCOPE: PUBLIC 2444** 2445** DESCRIPTION: 2446** 2447** This routine creates a duplicate handle to an existing 2448** (now shared) binding (via bumping a reference count). 2449** 2450** INPUTS: 2451** 2452** source_binding The binding handle which points to the source 2453** binding rep data structure to be copied. 2454** 2455** INPUTS/OUTPUTS: none 2456** 2457** OUTPUTS: 2458** 2459** destination_binding 2460** The binding handle which points to the shared 2461** binding rep data structure. 2462** 2463** status A value indicating the status of the routine. 2464** 2465** rpc_s_ok The call was successful. 2466** rpc_s_invalid_binding 2467** RPC Protocol ID in binding handle was invalid. 2468** rpc_s_coding_error 2469** 2470** IMPLICIT INPUTS: none 2471** 2472** IMPLICIT OUTPUTS: none 2473** 2474** FUNCTION VALUE: void 2475** 2476** SIDE EFFECTS: none 2477** 2478**-- 2479**/ 2480 2481 void rpc_binding_handle_copy 2482( 2483 rpc_binding_handle_t source_binding, 2484 rpc_binding_handle_t *destination_binding, 2485 unsigned32 *status 2486) 2487{ 2488 rpc_binding_rep_p_t src_binding_rep = (rpc_binding_rep_p_t) source_binding; 2489 rpc_binding_rep_p_t *dst_binding_rep = 2490 (rpc_binding_rep_p_t *) destination_binding; 2491 2492 assert(src_binding_rep != NULL); 2493 2494 CODING_ERROR (status); 2495 RPC_VERIFY_INIT (); 2496 2497 RPC_BINDING_VALIDATE_CLIENT(src_binding_rep, status); 2498 if (*status != rpc_s_ok) 2499 return; 2500 2501 /* 2502 * Add a new reference. 2503 */ 2504 2505 *dst_binding_rep = src_binding_rep; 2506 2507 RPC_LOCK(0); 2508 RPC_BINDING_REFERENCE(src_binding_rep); 2509 RPC_UNLOCK(0); 2510 2511 *status = rpc_s_ok; 2512} 2513 2514/* 2515**++ 2516** 2517** ROUTINE NAME: rpc_binding_handle_equal 2518** 2519** SCOPE: PUBLIC 2520** 2521** DESCRIPTION: 2522** 2523** This routine compares two binding handles to determine if they 2524** reference the same binding object. The current external binding handle 2525** representation (a pointer) doesn't really require the assistance 2526** of such a function, however, it is anticipated that we will (shortly) 2527** change the external representation to something that will allow us 2528** to detect dangling references users will not be able to perform a 2529** comparison via the C "==" operator. 2530** 2531** INPUTS: 2532** 2533** binding_h1 One binding handle ref. 2534** binding_h2 A second binding handle ref. 2535** 2536** INPUTS/OUTPUTS: none 2537** 2538** OUTPUTS: 2539** 2540** status A value indicating the status of the routine. 2541** 2542** rpc_s_ok The call was successful. 2543** 2544** IMPLICIT INPUTS: none 2545** 2546** IMPLICIT OUTPUTS: none 2547** 2548** FUNCTION VALUE: 2549** 2550** result true if both handle's refer to the same binding rep 2551** false if they don't 2552** 2553** SIDE EFFECTS: none 2554** 2555**-- 2556**/ 2557 2558PUBLIC boolean32 rpc_binding_handle_equal 2559( 2560 rpc_binding_handle_t binding1, 2561 rpc_binding_handle_t binding2, 2562 unsigned32 *status 2563) 2564{ 2565 CODING_ERROR (status); 2566 RPC_VERIFY_INIT (); 2567 2568 *status = rpc_s_ok; 2569 2570 return (binding1 == binding2); 2571} 2572 2573/* 2574**++ 2575** 2576** ROUTINE NAME: rpc_binding_server_to_client 2577** 2578** SCOPE: PUBLIC - declared in rpcpvt.idl 2579** 2580** DESCRIPTION: 2581** 2582** This routine provides compatibility for DCE components that were 2583** coded prior to the routine name change from rpc_binding_server_to_client() 2584** to rpc_binding_server_from_client(). 2585** 2586** This routine calls through to the rpc_binding_server_from_client() 2587** API routine. 2588** 2589** NOTE: This description uses old terminology. 2590** 2591** Convert a server binding handle to a client handle. The new handle's 2592** endpoint is reset and it has no associated authentication information. 2593** 2594** Server binding handles are those created by the runtime and provided 2595** to the server manager as a result of a [handle_t] RPC parameter. 2596** 2597** INPUTS: 2598** 2599** src_binding_h The binding handle which points to the (server) 2600** source binding rep data structure to be converted. 2601** 2602** INPUTS/OUTPUTS: none 2603** 2604** OUTPUTS: 2605** 2606** dst_binding_h The binding handle which points to the converted (client) 2607** destination binding rep data structure. 2608** 2609** status A value indicating the status of the routine. 2610** 2611** rpc_s_ok The call was successful. 2612** rpc_s_invalid_binding 2613** RPC Protocol ID in binding handle was invalid. 2614** rpc_s_coding_error 2615** 2616** IMPLICIT INPUTS: none 2617** 2618** IMPLICIT OUTPUTS: none 2619** 2620** FUNCTION VALUE: void 2621** 2622** SIDE EFFECTS: none 2623** 2624**-- 2625**/ 2626 2627PUBLIC void rpc_binding_server_to_client 2628( 2629 rpc_binding_handle_t src_binding_h, 2630 rpc_binding_handle_t *dst_binding_h, 2631 unsigned32 *status 2632) 2633{ 2634 rpc_binding_server_from_client (src_binding_h, dst_binding_h, status); 2635 return; 2636} 2637 2638/* 2639**++ 2640** 2641** ROUTINE NAME: rpc_binding_server_from_client 2642** 2643** SCOPE: PUBLIC - declared in rpc.idl 2644** 2645** DESCRIPTION: 2646** 2647** NOTE: This description and the code use phrases "server binding 2648** handle" and "client binding handle" opposite from the way 2649** these are used in the API documentation. At some point, we 2650** should change the code to match the documentation. 2651** 2652** Convert a server binding handle to a client handle. The new handle's 2653** endpoint is reset and it has no associated authentication information. 2654** 2655** Server binding handles are those created by the runtime and provided 2656** to the server manager as a result of a [handle_t] RPC parameter. 2657** 2658** INPUTS: 2659** 2660** src_binding_h The binding handle which points to the (server) 2661** source binding rep data structure to be converted. 2662** 2663** INPUTS/OUTPUTS: none 2664** 2665** OUTPUTS: 2666** 2667** dst_binding_h The binding handle which points to the converted (client) 2668** destination binding rep data structure. 2669** 2670** status A value indicating the status of the routine. 2671** 2672** rpc_s_ok The call was successful. 2673** rpc_s_invalid_binding 2674** RPC Protocol ID in binding handle was invalid. 2675** rpc_s_coding_error 2676** 2677** IMPLICIT INPUTS: none 2678** 2679** IMPLICIT OUTPUTS: none 2680** 2681** FUNCTION VALUE: void 2682** 2683** SIDE EFFECTS: none 2684** 2685**-- 2686**/ 2687 2688PUBLIC void rpc_binding_server_from_client 2689( 2690 rpc_binding_handle_t src_binding_h, 2691 rpc_binding_handle_t *dst_binding_h, 2692 unsigned32 *status 2693 ) 2694{ 2695 rpc_binding_rep_p_t src_binding_rep = (rpc_binding_rep_p_t) src_binding_h; 2696 rpc_binding_rep_p_t dst_binding_rep; 2697 rpc_addr_p_t rpc_addr; 2698 unsigned32 tmp_status; 2699 boolean have_addr = false; 2700 2701 assert(src_binding_rep != NULL); 2702 2703 CODING_ERROR (status); 2704 RPC_VERIFY_INIT (); 2705 2706 RPC_BINDING_VALIDATE_SERVER(src_binding_rep, status); 2707 if (*status != rpc_s_ok) 2708 return; 2709 2710 /* 2711 * if the RPC address in the source is NULL, get one from protocol service 2712 */ 2713 if (src_binding_rep->rpc_addr == NULL) 2714 { 2715 rpc_addr_p_t srpc_addr; 2716 2717 (*rpc_g_protocol_id[src_binding_rep->protocol_id].binding_epv 2718 ->binding_inq_addr) (src_binding_rep, &srpc_addr, status); 2719 2720 if (*status != rpc_s_ok) 2721 return; 2722 2723 /* 2724 * make a copy of the one in the source 2725 */ 2726 (*rpc_g_naf_id[src_binding_rep->rpc_addr->sa.family].epv 2727 ->naf_addr_copy) 2728 (src_binding_rep->rpc_addr, &rpc_addr, status); 2729 2730 } 2731 else 2732 { 2733 /* 2734 * otherwise, make a copy of the one in the source 2735 */ 2736 (*rpc_g_naf_id[src_binding_rep->rpc_addr->sa.family].epv 2737 ->naf_addr_copy) 2738 (src_binding_rep->rpc_addr, &rpc_addr, status); 2739 if (*status != rpc_s_ok) return; 2740 } 2741 have_addr = true; 2742 2743 /* 2744 * The resultant binding's address has no endpoint. It is absolutely 2745 * wrong to use the originating client's endpoint. 2746 */ 2747 rpc__naf_addr_set_endpoint ((unsigned_char_p_t) "", &rpc_addr, status); 2748 if (*status != rpc_s_ok) goto CLEANUP; 2749 2750 /* 2751 * allocate and init a *client* binding rep. 2752 */ 2753 dst_binding_rep = rpc__binding_alloc ( 2754 false, &src_binding_rep->obj, 2755 src_binding_rep->protocol_id, rpc_addr, status); 2756 if (*status != rpc_s_ok) goto CLEANUP; 2757 2758 /* 2759 * copy other common parts of the binding rep from the source to dest 2760 * 2761 * We explicitly leave the dst->auth NULL; the server (using this 2762 * new client handle) probably wants to make calls as its own 2763 * identity. 2764 */ 2765 dst_binding_rep->timeout = src_binding_rep->timeout; 2766 dst_binding_rep->call_timeout_time = src_binding_rep->call_timeout_time; 2767 dst_binding_rep->addr_is_dynamic = src_binding_rep->addr_is_dynamic; 2768 2769 /* 2770 * return the destination binding rep as a binding handle 2771 */ 2772 *dst_binding_h = (rpc_binding_handle_t) dst_binding_rep; 2773 2774 *status = rpc_s_ok; 2775 2776CLEANUP: 2777 2778 if (*status != rpc_s_ok && have_addr) 2779 rpc__naf_addr_free (&rpc_addr, &tmp_status); 2780} 2781 2782 2783/* 2784**++ 2785** 2786** ROUTINE NAME: rpc__binding_inq_sockaddr 2787** 2788** SCOPE: PRIVATE - declared in com.h 2789** 2790** DESCRIPTION: 2791** 2792** Inquire the sockaddr that is associated with a binding handle. 2793** 2794** This is kernel RPC only (private) operation and exists strictly for 2795** performance reasons. The returned sockaddr pointer points to storage 2796** directly associated with the binding handle. This pointer can become 2797** invalid under a number of circumstances (e.g. binding handle 2798** operations); copy the sa if you need to use it after any binding handle 2799** operations! 2800** 2801** Note: Do NOT remove this routine even though it appears that nothing 2802** is using it... it is used by Kernel RPC Applications. 2803** 2804** INPUTS: 2805** 2806** binding_h The binding handle which points to the binding 2807** rep data structure to be inquired. 2808** 2809** INPUTS/OUTPUTS: none 2810** 2811** OUTPUTS: 2812** 2813** sa A pointer to the sockaddr contained in the binding. 2814** 2815** status A value indicating the status of the routine. 2816** 2817** rpc_s_ok The call was successful. 2818** 2819** IMPLICIT INPUTS: none 2820** 2821** IMPLICIT OUTPUTS: none 2822** 2823** FUNCTION VALUE: void 2824** 2825** SIDE EFFECTS: none 2826** 2827**-- 2828**/ 2829 2830PRIVATE void rpc__binding_inq_sockaddr 2831( 2832 rpc_binding_handle_t binding_h, 2833 sockaddr_p_t *sa, 2834 unsigned32 *status 2835) 2836{ 2837 *sa = &((rpc_binding_rep_p_t) binding_h)->rpc_addr->sa; 2838 2839 *status = rpc_s_ok; 2840} 2841 2842/* 2843**++ 2844** 2845** ROUTINE NAME: rpc__binding_cross_fork 2846** 2847** SCOPE: PRIVATE - declared in com.h 2848** 2849** DESCRIPTION: 2850** 2851** Perform whatever actions are required to make a binding handle usable 2852** in the client of a fork. 2853** 2854** Currently there is no common processing performed, and we just pass 2855** the binding rep to protocol specific routines for processing. 2856** 2857** INPUTS: 2858** 2859** binding_rep A pointer to a binding rep which is being used 2860** across a fork. 2861** 2862** INPUTS/OUTPUTS: none 2863** 2864** OUTPUTS: 2865** 2866** status A value indicating the status of the routine. 2867** 2868** rpc_s_ok The call was successful. 2869** 2870** IMPLICIT INPUTS: none 2871** 2872** IMPLICIT OUTPUTS: none 2873** 2874** FUNCTION VALUE: void 2875** 2876** SIDE EFFECTS: Any state associated with the binding handle is 2877** dropped so that it is not inherited by the child 2878** of a fork. 2879** 2880**-- 2881**/ 2882 2883PRIVATE void rpc__binding_cross_fork 2884( 2885 rpc_binding_rep_p_t binding_rep, 2886 unsigned32 * status 2887) 2888{ 2889 /* 2890 * Servers aren't allowed to fork, so we only allow passing 2891 * client binding handles across the fork. 2892 */ 2893 if (! RPC_BINDING_IS_CLIENT(binding_rep)) 2894 { 2895 *status = rpc_s_wrong_kind_of_binding; 2896 return; 2897 } 2898 2899 /* 2900 * We only want to bring the handle across the fork once. 2901 * Take the global lock, then check that the handle still 2902 * needs to cross the fork. 2903 */ 2904 RPC_LOCK(0); 2905 2906 if (binding_rep->fork_count != rpc_g_fork_count) 2907 { 2908 /* 2909 * Ask the protocol service to clean up any protocol specific 2910 * state that should not survive in the child of a fork. 2911 */ 2912 (*rpc_g_protocol_id[binding_rep->protocol_id].binding_epv 2913 ->binding_cross_fork) (binding_rep, status); 2914 2915 /* 2916 * Update the handle to the current fork count. 2917 */ 2918 binding_rep->fork_count = rpc_g_fork_count; 2919 } 2920 2921 RPC_UNLOCK(0); 2922} 2923 2924/* 2925**++ 2926** ROUTINE NAME: rpc__binding_prot_version_alloc 2927** 2928** SCOPE: PRIVATE 2929** 2930** DESCRIPTION: 2931** 2932** Allocates and initializes an rpc_protocol_version_t struct. 2933** 2934** INPUTS: 2935** major_version The major version of the protocol 2936** 2937** minor_version The minor version of the protocol. 2938** 2939** 2940** OUTPUTS: 2941** prot_version The allocated protocol_version structure. 2942** 2943** status 2944** rpc_s_ok 2945** 2946** 2947** IMPLICIT INPUTS: none 2948** 2949** IMPLICIT OUTPUTS: none 2950** 2951** FUNCTION VALUE: void 2952** 2953** SIDE EFFECTS: none 2954** 2955**-- 2956*/ 2957PRIVATE void rpc__binding_prot_version_alloc( 2958 rpc_protocol_version_p_t *prot_version, 2959 unsigned32 major_version, 2960 unsigned32 minor_version, 2961 unsigned32 *status) 2962 2963{ 2964 2965 /* 2966 * Alocate a version struct 2967 */ 2968 RPC_MEM_ALLOC(*prot_version, 2969 rpc_protocol_version_p_t, 2970 sizeof(rpc_protocol_version_t), 2971 RPC_C_MEM_PROTOCOL_VERSION, 2972 RPC_C_MEM_WAITOK); 2973 2974 /* 2975 * Initialize data 2976 */ 2977 (*prot_version)->major_version = major_version; 2978 (*prot_version)->minor_version = minor_version; 2979 2980 *status = rpc_s_ok; 2981 2982 return; 2983} 2984 2985 2986/* 2987**++ 2988** ROUTINE NAME: rpc__binding_prot_version_free 2989** 2990** SCOPE: PRIVATE - declared in com.h 2991** 2992** DESCRIPTION: 2993** 2994** Free's an rpc_protocol_version_t struct. 2995** The pointer is set to NULL. 2996** 2997** INPUTS: 2998** protocol_version Pointer to the version stuct. 2999** 3000** 3001** OUTPUTS: none 3002** 3003** SIDE EFFECTS: none 3004** 3005**-- 3006*/ 3007PRIVATE void rpc__binding_prot_version_free( 3008 rpc_protocol_version_p_t *protocol_version) 3009 3010{ 3011 RPC_MEM_FREE (*protocol_version, RPC_C_MEM_PROTOCOL_VERSION); 3012 *protocol_version = NULL; 3013 3014 return; 3015} 3016 3017 3018/* 3019**++ 3020** ROUTINE NAME: rpc__binding_set_prot_version 3021** 3022** SCOPE: PRIVATE - called from nslookup.c 3023** 3024** DESCRIPTION: 3025** 3026** Sets the protocol version in a binding_rep data structure 3027** from a protocol tower. 3028** 3029** INPUTS: 3030** binding_h The binding handle which points to the binding 3031** rep data structure to be modified. 3032** 3033** tower_ref The tower to get the protocol version information 3034** 3035** OUTPUTS: 3036** status return status from called routines. 3037** 3038** SIDE EFFECTS: none 3039** 3040**-- 3041*/ 3042PRIVATE void rpc__binding_set_prot_version( 3043 rpc_binding_handle_t binding_h, 3044 rpc_tower_ref_p_t tower_ref, 3045 unsigned32 *status) 3046{ 3047 rpc_binding_rep_p_t binding_rep; 3048 rpc_protocol_id_t temp_protocol_id; 3049 unsigned32 major_version; 3050 unsigned32 minor_version; 3051 3052 /* 3053 * Get the major and minor version of the tower. 3054 */ 3055 rpc__tower_flr_to_rpc_prot_id(tower_ref->floor[2], 3056 &temp_protocol_id, 3057 &major_version, 3058 &minor_version, 3059 status); 3060 3061 if (*status != rpc_s_ok) 3062 { 3063 return; 3064 } 3065 3066 /* 3067 * Allocate a protocol structure and initialize it. 3068 */ 3069 binding_rep = (rpc_binding_rep_p_t) binding_h; 3070 rpc__binding_prot_version_alloc(&(binding_rep->protocol_version), 3071 major_version, 3072 minor_version, 3073 status); 3074 3075 return; 3076} 3077 3078 3079/* 3080**++ 3081** ROUTINE NAME: rpc_binding_create 3082** 3083** SCOPE: PUBLIC 3084** 3085** DESCRIPTION: 3086** 3087** INPUTS: 3088** template binding handle template 3089** 3090** security security options 3091** 3092** options other options 3093** 3094** OUTPUTS: 3095** binding_h binding handle 3096** 3097** status return status from called routines. 3098** 3099** SIDE EFFECTS: none 3100** 3101**-- 3102*/ 3103PUBLIC void rpc_binding_create( 3104 rpc_binding_handle_template_t *template, 3105 rpc_binding_handle_security_t *security, 3106 rpc_binding_handle_options_t *options, 3107 rpc_binding_handle_t *binding_h, 3108 unsigned32 *st) 3109{ 3110 unsigned_char_p_t string_object_uuid = NULL; 3111 unsigned_char_p_t string_binding = NULL; 3112 rpc_binding_handle_t h = NULL; 3113 unsigned32 tmp_st; 3114 3115 CODING_ERROR(st); 3116 3117 *binding_h = NULL; 3118 3119 if (template->version != 1 || 3120 (security != NULL && security->version != 1) || 3121 (options != NULL && options->version != 1)) 3122 { 3123 *st = rpc_s_rpc_prot_version_mismatch; /* XXX */ 3124 return; 3125 } 3126 3127 if (!uuid_is_nil(&template->object_uuid, st)) 3128 { 3129 uuid_to_string(&template->object_uuid, &string_binding, st); 3130 if (*st != rpc_s_ok) 3131 return; 3132 } 3133 3134 rpc_string_binding_compose(string_object_uuid, 3135 template->protseq, 3136 template->network_address, 3137 template->string_endpoint, 3138 template->reserved, 3139 &string_binding, 3140 st); 3141 rpc_string_free(&string_object_uuid, &tmp_st); 3142 if (*st != rpc_s_ok) 3143 return; 3144 3145 rpc_binding_from_string_binding(string_binding, &h, st); 3146 rpc_string_free(&string_binding, &tmp_st); 3147 if (*st != rpc_s_ok) 3148 return; 3149 3150 if (*st == rpc_s_ok && h == NULL) 3151 { 3152 *st = rpc_s_no_bindings; 3153 return; 3154 } 3155 3156 if (options != NULL) 3157 { 3158 rpc_mgmt_set_com_timeout(h, options->com_timeout, st); 3159 if (*st != rpc_s_ok) 3160 { 3161 rpc_binding_free(&h, &tmp_st); 3162 return; 3163 } 3164 rpc_mgmt_set_cancel_timeout(options->cancel_timeout, st); 3165 if (*st != rpc_s_ok) 3166 { 3167 rpc_binding_free(&h, &tmp_st); 3168 return; 3169 } 3170 } 3171 3172 if (security != NULL) 3173 { 3174 rpc_binding_set_auth_info(h, 3175 security->server_princ_name, 3176 security->authn_level, 3177 security->authn_protocol, 3178 security->auth_identity, 3179 security->authz_svc, 3180 st); 3181 if (*st != rpc_s_ok) 3182 { 3183 rpc_binding_free(&h, &tmp_st); 3184 return; 3185 } 3186 } 3187 3188 *binding_h = h; 3189 3190 return; 3191} 3192