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** cnbind.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** The NCA Connection Protocol Service's Binding Service. 90** 91** 92*/ 93 94#include <commonp.h> /* Common declarations for all RPC runtime */ 95#include <com.h> /* Common communications services */ 96#include <comprot.h> /* Common protocol services */ 97#include <cnp.h> /* NCA Connection private declarations */ 98#include <cnpkt.h> /* NCA Connection packet encoding */ 99#include <cnassoc.h> /* NCA Connection association service */ 100#include <cnid.h> /* NCA Connection local id service */ 101#include <cnbind.h> 102 103 104/* 105**++ 106** 107** ROUTINE NAME: rpc__cn_binding_alloc 108** 109** SCOPE: PRIVATE - declared in cnbind.h 110** 111** DESCRIPTION: 112** 113** This routine will allocate a binding rep data structure. A 114** binding rep contains a protocol specific part and therefore 115** must be allocated by the protocol service. 116** 117** INPUTS: 118** 119** is_server Boolean indicating server-side binding handle should 120** be created. 121** 122** INPUTS/OUTPUTS: none 123** 124** OUTPUTS: 125** 126** st The return status of this routine. 127** 128** IMPLICIT INPUTS: none 129** 130** IMPLICIT OUTPUTS: none 131** 132** FUNCTION VALUE: 133** 134** return The allocated binding rep structure. 135** rpc_s_ok 136** 137** SIDE EFFECTS: none 138** 139**-- 140**/ 141 142PRIVATE rpc_binding_rep_t *rpc__cn_binding_alloc 143( 144 boolean32 is_server, 145 unsigned32 *st 146) 147{ 148 rpc_cn_binding_rep_p_t brp; 149 150 CODING_ERROR (st); 151 152 /* 153 * A server binding is allocated from the receiver thread which 154 * has already acquired the CN global mutex. 155 */ 156 if (!is_server) 157 { 158 RPC_CN_LOCK (); 159 } 160 else 161 { 162 RPC_CN_LOCK_ASSERT (); 163 } 164 165 /* 166 * Allocate a binding rep off the lookaside list. 167 */ 168 brp = (rpc_cn_binding_rep_p_t) 169 rpc__list_element_alloc (&rpc_g_cn_binding_lookaside_list, 170 true); 171 if (brp == NULL) 172 { 173 *st = rpc_s_no_memory; 174 RPC_CN_UNLOCK (); 175 return NULL; 176 } 177 if (!is_server) 178 { 179 ((rpc_cn_binding_rep_t *)brp)->being_resolved = false; 180 RPC_CN_UNLOCK (); 181 } 182 183 brp->common.rpc_addr = NULL; 184 brp->common.auth_info = NULL; 185 brp->common.transport_info = NULL; 186 187 *st = rpc_s_ok; 188 return ((rpc_binding_rep_p_t) brp); 189} 190 191 192/* 193**++ 194** 195** ROUTINE NAME: rpc__cn_binding_init 196** 197** SCOPE: PRIVATE - declared in cnbind.h 198** 199** DESCRIPTION: 200** 201** This routine will initialize the protocol specific part of a 202** previously allocated binding rep data structure. For the NCA 203** Connection protocol this means locating an association group 204** whose primary address matches that in the binding rep. Note 205** that this can only be done if an RPC address is supplied. 206** 207** INPUTS: 208** 209** binding_r The binding rep to be initialized. 210** 211** INPUTS/OUTPUTS: none 212** 213** OUTPUTS: 214** 215** st The return status of this routine. 216** 217** IMPLICIT INPUTS: none 218** 219** IMPLICIT OUTPUTS: none 220** 221** FUNCTION VALUE: 222** 223** rpc_s_coding_error 224** rpc_s_ok 225** 226** SIDE EFFECTS: none 227** 228**-- 229**/ 230 231PRIVATE void rpc__cn_binding_init 232( 233 rpc_binding_rep_p_t binding_r, 234 unsigned32 *st 235) 236{ 237 unsigned32 type; 238 rpc_cn_local_id_t grp_id; 239 240 CODING_ERROR (st); 241 242 /* 243 * Determine the type of association group we are looking for. 244 */ 245 if (RPC_BINDING_IS_SERVER (binding_r)) 246 { 247 //type = RPC_C_CN_ASSOC_GRP_SERVER; 248 } 249 else 250 { 251 type = RPC_C_CN_ASSOC_GRP_CLIENT; 252 253 /* 254 * Use the RPC address contained in the binding rep to find an 255 * association group. 256 */ 257 RPC_CN_LOCK (); 258 grp_id = rpc__cn_assoc_grp_lkup_by_addr (binding_r->rpc_addr, 259 binding_r->transport_info, 260 type, 261 st); 262 263 /* 264 * Record its the association group id returned into the 265 * binding rep. Note that the group id returned may be invalid. 266 */ 267 ((rpc_cn_binding_rep_t *)binding_r)->grp_id = grp_id; 268 RPC_CN_UNLOCK (); 269 } 270 271 /* 272 * Return a good status code no matter what happened. 273 */ 274 *st = rpc_s_ok; 275} 276 277 278/* 279**++ 280** 281** ROUTINE NAME: rpc__cn_binding_reset 282** 283** SCOPE: PRIVATE - declared in cnbind.h 284** 285** DESCRIPTION: 286** 287** This routine will clear the endpoint in the RPC address 288** contained in the binding rep data structure given. 289** 290** INPUTS: 291** 292** binding_r The binding rep containing the RPC address 293** to be reset. 294** 295** INPUTS/OUTPUTS: none 296** 297** OUTPUTS: 298** 299** st The return status of this routine. 300** 301** IMPLICIT INPUTS: none 302** 303** IMPLICIT OUTPUTS: none 304** 305** FUNCTION VALUE: 306** 307** rpc_s_coding_error 308** rpc_s_ok 309** 310** SIDE EFFECTS: none 311** 312**-- 313**/ 314 315PRIVATE void rpc__cn_binding_reset 316( 317 rpc_binding_rep_p_t binding_r, 318 unsigned32 *st 319) 320{ 321 CODING_ERROR (st); 322 323 /* 324 * The endpoint in the binding is being reset. Since we assume 325 * endpoints are tied to address spaces and an association group 326 * id identifies an address space we should reset the group ID. 327 * When the endpoint is added to the binding 328 * rpc__cn_binding_init should be called again to set the group id. 329 */ 330 RPC_CN_LOCAL_ID_CLEAR (((rpc_cn_binding_rep_t *)binding_r)->grp_id); 331 332 *st = rpc_s_ok; 333} 334 335 336/* 337**++ 338** 339** ROUTINE NAME: rpc__cn_binding_changed 340** 341** SCOPE: PRIVATE - declared in cnbind.h 342** 343** DESCRIPTION: 344** 345** This routine is called when something in the common part of 346** the binding rep given has changed. 347** 348** INPUTS: 349** 350** binding_r The binding rep which changed. 351** 352** INPUTS/OUTPUTS: none 353** 354** OUTPUTS: 355** 356** st The return status of this routine. 357** 358** IMPLICIT INPUTS: none 359** 360** IMPLICIT OUTPUTS: none 361** 362** FUNCTION VALUE: 363** 364** rpc_s_coding_error 365** rpc_s_ok 366** 367** SIDE EFFECTS: none 368** 369**-- 370**/ 371 372PRIVATE void rpc__cn_binding_changed 373( 374 rpc_binding_rep_p_t binding_r, 375 unsigned32 *st 376) 377{ 378 CODING_ERROR (st); 379 380 /* 381 * The exact field which changed is not known. Init the binding. 382 */ 383 rpc__cn_binding_init (binding_r, st); 384} 385 386 387/* 388**++ 389** 390** ROUTINE NAME: rpc__cn_binding_free 391** 392** SCOPE: PRIVATE - declared in cnbind.h 393** 394** DESCRIPTION: 395** 396** This routine frees the binding rep data structure given. 397** 398** INPUTS: none 399** 400** INPUTS/OUTPUTS: 401** 402** binding_r The binding rep to be freed 403** 404** OUTPUTS: 405** 406** st The return status of this routine. 407** 408** IMPLICIT INPUTS: none 409** 410** IMPLICIT OUTPUTS: none 411** 412** FUNCTION VALUE: 413** 414** rpc_s_coding_error 415** rpc_s_ok 416** 417** SIDE EFFECTS: none 418** 419**-- 420**/ 421 422PRIVATE void rpc__cn_binding_free 423( 424 rpc_binding_rep_p_t *binding_r, 425 unsigned32 *st 426) 427{ 428 CODING_ERROR (st); 429 430 RPC_CN_LOCK_ASSERT (); 431 432 /* 433 * Put the binding rep back on the lookaside list. 434 */ 435 rpc__list_element_free (&rpc_g_cn_binding_lookaside_list, 436 (dce_pointer_t) *binding_r); 437 438 /* 439 * Null the caller's pointer to this memory. 440 */ 441 *binding_r = NULL; 442 *st = rpc_s_ok; 443} 444 445 446/* 447**++ 448** 449** ROUTINE NAME: rpc__cn_binding_inq_addr 450** 451** SCOPE: PRIVATE - declared in cnbind.h 452** 453** DESCRIPTION: 454** 455** This routine allocates and returns the RPC address 456** associated with the binding rep data structure given. 457** 458** INPUTS: 459** 460** binding_r The binding rep to be freed 461** 462** INPUTS/OUTPUTS: 463** 464** rpc_addr The RPC address which is allocated. 465** 466** OUTPUTS: 467** 468** st The return status of this routine. 469** 470** IMPLICIT INPUTS: none 471** 472** IMPLICIT OUTPUTS: none 473** 474** FUNCTION VALUE: 475** 476** rpc_s_coding_error 477** rpc_s_ok 478** rpc_s_assoc_grp_not_found 479** 480** SIDE EFFECTS: none 481** 482**-- 483**/ 484 485PRIVATE void rpc__cn_binding_inq_addr 486( 487 rpc_binding_rep_p_t binding_r, 488 rpc_addr_p_t *rpc_addr, 489 unsigned32 *st 490) 491{ 492 unsigned32 type; 493 rpc_cn_local_id_t grp_id; 494 rpc_cn_assoc_grp_t *assoc_grp; 495 rpc_protseq_id_t protseq_id; 496 497 CODING_ERROR (st); 498 499 /* 500 * Determine the type of association group we are looking for. 501 */ 502 if (RPC_BINDING_IS_SERVER (binding_r)) 503 { 504 type = RPC_C_CN_ASSOC_GRP_SERVER; 505 } 506 else 507 { 508 type = RPC_C_CN_ASSOC_GRP_CLIENT; 509 } 510 511 /* 512 * Use the group id contained in the binding rep to find an 513 * association group. 514 */ 515 RPC_CN_LOCK (); 516 grp_id = rpc__cn_assoc_grp_lkup_by_id ( 517 ((rpc_cn_binding_rep_t *)binding_r)->grp_id, 518 type, 519 binding_r->transport_info, 520 st); 521 522 /* 523 * Check whether an association group was found or not. 524 */ 525 if (RPC_CN_LOCAL_ID_VALID (grp_id)) 526 { 527 /* 528 * An association group was found. Check whether it 529 * contains an RPC address. 530 */ 531 assoc_grp = RPC_CN_ASSOC_GRP (grp_id); 532 assert(assoc_grp != NULL); 533 if (assoc_grp->grp_address != NULL) 534 { 535 /* 536 * The association group contains an RPC address. 537 * Copy it into the binding. 538 */ 539 rpc__naf_addr_copy (assoc_grp->grp_address, 540 rpc_addr, 541 st); 542 } 543 else 544 { 545 /* 546 * The association doesn't have an RPC address. Find 547 * it out using one of the connections attached to the 548 * association group. 549 */ 550 rpc__naf_desc_inq_protseq_id 551 (((rpc_cn_assoc_t *)assoc_grp->grp_assoc_list.next)->cn_ctlblk.cn_sock, 552 RPC_C_PROTOCOL_ID_NCACN, 553 &protseq_id, 554 st); 555 if (*st == rpc_s_ok) 556 { 557 rpc__naf_desc_inq_peer_addr 558 (((rpc_cn_assoc_t *)assoc_grp->grp_assoc_list.next)->cn_ctlblk.cn_sock, 559 protseq_id, 560 rpc_addr, 561 st); 562 if (*st == rpc_s_ok) 563 { 564 rpc__naf_addr_copy (*rpc_addr, 565 &assoc_grp->grp_address, 566 st); 567 } 568 } 569 } 570 binding_r->rpc_addr = *rpc_addr; 571 } 572 else 573 { 574 *st = rpc_s_connection_closed; 575 } 576 RPC_CN_UNLOCK (); 577} 578 579 580/* 581**++ 582** 583** ROUTINE NAME: rpc__cn_binding_inq_client 584** 585** SCOPE: PRIVATE - declared in cnbind.h 586** 587** DESCRIPTION: 588** 589** This routine returns the client process identifier, i.e. the 590** association group id, for a given binding rep. 591** 592** INPUTS: 593** 594** binding_r The binding rep to be freed 595** 596** INPUTS/OUTPUTS: 597** 598** rpc_addr The RPC address which is allocated. 599** 600** OUTPUTS: 601** 602** st The return status of this routine. 603** 604** IMPLICIT INPUTS: none 605** 606** IMPLICIT OUTPUTS: none 607** 608** FUNCTION VALUE: 609** 610** rpc_s_coding_error 611** rpc_s_ok 612** 613** SIDE EFFECTS: none 614** 615**-- 616**/ 617 618PRIVATE void rpc__cn_binding_inq_client 619( 620 rpc_binding_rep_p_t binding_r, 621 rpc_client_handle_t *client_h, 622 unsigned32 *st 623) 624{ 625 rpc_cn_local_id_t grp_id; 626 627 CODING_ERROR (st); 628 629 /* 630 * Get the association group id from the binding rep. 631 */ 632 grp_id = ((rpc_cn_binding_rep_t *)binding_r)->grp_id; 633 634 /* 635 * Make sure the group id is valid. 636 */ 637 *client_h = (rpc_client_handle_t) grp_id.all; 638 if (RPC_CN_LOCAL_ID_VALID (grp_id)) 639 { 640 *st = rpc_s_ok; 641 } 642 else 643 { 644 *st = rpc_s_invalid_binding; 645 } 646} 647 648/* 649**++ 650** 651** ROUTINE NAME: rpc__cn_binding_copy 652** 653** SCOPE: PRIVATE - declared in cnbind.h 654** 655** DESCRIPTION: 656** 657** This routine will init the CN specific fields of a copied 658** binding rep. 659** 660** INPUTS: 661** 662** src_binding_r The binding rep to be copied. 663** dst_binding_r The binding rep being copied into. 664** 665** INPUTS/OUTPUTS: none 666** 667** OUTPUTS: 668** 669** st The return status of this routine. 670** 671** IMPLICIT INPUTS: none 672** 673** IMPLICIT OUTPUTS: none 674** 675** FUNCTION VALUE: 676** 677** rpc_s_coding_error 678** rpc_s_ok 679** 680** SIDE EFFECTS: none 681** 682**-- 683**/ 684 685PRIVATE void rpc__cn_binding_copy 686( 687 rpc_binding_rep_p_t src_binding_r, 688 rpc_binding_rep_p_t dst_binding_r, 689 unsigned32 *st 690) 691{ 692 CODING_ERROR (st); 693 694 /* 695 * Get the association group id from the src binding rep and put 696 * it in the dst binding rep. 697 */ 698 ((rpc_cn_binding_rep_t *)dst_binding_r)->grp_id = 699 ((rpc_cn_binding_rep_t *)src_binding_r)->grp_id; 700 701 *st = rpc_s_ok; 702} 703 704 705/* 706**++ 707** 708** ROUTINE NAME: rpc__cn_binding_cross_fork 709** 710** SCOPE: PRIVATE - declared in cnbind.h 711** 712** DESCRIPTION: 713** 714** This routine makes it possible for children of forks to use 715** binding handles inherited from their parents. 716** 717** INPUTS: 718** 719** binding_r The binding rep to be inherited 720** 721** INPUTS/OUTPUTS: none 722** 723** OUTPUTS: 724** 725** st The return status of this routine. 726** 727** IMPLICIT INPUTS: none 728** 729** IMPLICIT OUTPUTS: none 730** 731** FUNCTION VALUE: 732** 733** rpc_s_coding_error 734** rpc_s_ok 735** 736** SIDE EFFECTS: none 737** 738**-- 739**/ 740 741PRIVATE void rpc__cn_binding_cross_fork 742( 743 rpc_binding_rep_p_t binding_r ATTRIBUTE_UNUSED, 744 unsigned32 *st 745) 746{ 747 CODING_ERROR (st); 748 749 /* 750 * This is a dummy function to avoid the null reference 751 * causing a core dump. 752 */ 753 754 *st = rpc_s_ok; 755} 756