/* * Copyright (c) 2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Inc. ("Apple") nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Portions of this software have been released under the following terms: * * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION * * To anyone who acknowledges that this file is provided "AS IS" * without any express or implied warranty: * permission to use, copy, modify, and distribute this file for any * purpose is hereby granted without fee, provided that the above * copyright notices and this notice appears in all source code copies, * and that none of the names of Open Software Foundation, Inc., Hewlett- * Packard Company or Digital Equipment Corporation be used * in advertising or publicity pertaining to distribution of the software * without specific, written prior permission. Neither Open Software * Foundation, Inc., Hewlett-Packard Company nor Digital * Equipment Corporation makes any representations about the suitability * of this software for any purpose. * * Copyright (c) 2007, Novell, Inc. All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Novell Inc. nor the names of its contributors * may be used to endorse or promote products derived from this * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @APPLE_LICENSE_HEADER_END@ */ /* ** ** NAME ** ** comp.c ** ** FACILITY: ** ** Remote Procedure Call (RPC) ** ** ABSTRACT: ** ** Definitions of storage internal to Common Communications Service component. ** ** */ #include <commonp.h> /* Common internals for RPC Runtime system */ #include <com.h> /* Externals for Common Services component */ #include <comprot.h> /* Externals for common Protocol Services */ #include <comnaf.h> /* Externals for common NAF Services */ #include <comp.h> /* Internals for Common Services component */ #include <comfwd.h> /* Externals for Common Services Fwd component */ /***********************************************************************/ /* * R P C _ G _ I N I T I A L I Z E D * * The value that indicates whether or not the RPC runtime has previously * been initialized (via a call to rpc__init). Its declaration is * in com.h since the Naming Service may need to invoke the * RPC_VERIFY_INIT macro. */ GLOBAL boolean rpc_g_initialized = false; /***********************************************************************/ /* * R P C _ G _ T H R E A D _ C O N T E X T _ K E Y * * The key visible to all threads that contains a pointer to the * per-thread context block. */ GLOBAL dcethread_key rpc_g_thread_context_key; /***********************************************************************/ /* * R P C _ G _ G L O B A L _ M U T E X * * The global mutex used for the entire Communications Service. Note * that this may be temporary since a per-data structure mutex may * be employed. Its declaration is in com.h since RPC Protocol * Services will need to reference it through the mutex macros. */ GLOBAL rpc_mutex_t rpc_g_global_mutex; /***********************************************************************/ /* * R P C _ G _ G L O B A L _ B I N D I N G _ C O N D * * The global binding handle condition variable used for call * serialization. This condition variable is protected by the global * mutex. Note that this may be temporary since a per-binding handle * cond var / mutex may be employed. */ GLOBAL rpc_cond_t rpc_g_global_binding_cond; /***********************************************************************/ /* * R P C _ G _ F O R K _ C O U N T * * The global fork count used to detect when a process using * RPC has forked. After a fork, the parent is allowed to proceed * unaffected--all RPC helper threads are restarted, and * all RPC state maintained. In the child, however, all state * is dropped, and the RPC initialization process will have * to be repeated if the child tries to use RPC. * * The counter here is necessitated by the fact that it is possible * for the application to hold the only reference to certain * data structures allocated by the runtime; the example of concern * here is binding handles. Since we have no way at present * of tracking dow these binding handles during the normal fork * handling, we need some way to recognize them if the application * tries to use one *after* the fork. By storing the current * global fork count in each handle, and then incrementing the * global count in the child of a fork, we can recognize such * handles the next time they are used. Protocol specific routine * are then called to perform whatever actions are necessary to * drop any state associated with the handle. * * Note that we are currently stranding memory across forks; eg. * call handles, mutexes, etc. This is considered a necessary and * acceptable evil based on the following considerations: * * 1) The reset/release/etc. routines that exist today are * designed to carry out any pending operations associated * with the data structure. For example, before freeing * a call handle, the DG code will try to send out any * pending acknowledgements. For this reason, most of * these routines are unusable. * 2) It is too late to redesign all of these routines to * incorporate the correct fork-aware behavior. * 3) Vaporizing all state in the child of a fork creates a * scenario that is easier to understand, and implement * correctly. * 4) The amount of memory stranded does not seem to be enough * to worry about. We are assuming that the child of * a fork will not itself fork a child that will itself * fork a child, etc., eventually filling the VA space * with stranded memory. */ GLOBAL unsigned32 rpc_g_fork_count; /***********************************************************************/ /* * R P C _ G _ F W D _ F N * * The global forwarding map function variable. Its value indicates * whether or not the RPC runtime should be performing forwarding services * and if so, the forwarding map function to use. */ GLOBAL rpc_fwd_map_fn_t rpc_g_fwd_fn = NULL; /***********************************************************************/ /* * R P C _ G _ S E R V E R _ P T H R E A D _ A T T R * * A dcethread attribute for server thread creation. * Initialized by rpc_init(). */ GLOBAL dcethread_attr rpc_g_server_dcethread_attr; /***********************************************************************/ /* * R P C _ G _ R U N T I M E _ P T H R E A D _ A T T R * * A dcethread attribute for internal thread creation. This parameter * is of particular interest to those threads internal to the runtime * that can call security routines. These threads include: the * network listener and the receiver threads. * Initialized by rpc_init(). */ GLOBAL dcethread_attr rpc_g_default_dcethread_attr; /***********************************************************************/ /* * RPCMEM package statistics. Extern'd in "rpcmem.h>. * * ### !!! seems like this should be in the (non-existent) "rpcmem.c" file. */ GLOBAL rpc_mem_stats_elt_t rpc_g_mem_stats[RPC_C_MEM_MAX_TYPES]; /***********************************************************************/ /* * R P C _ G _ N S _ S P E C I F I C _ F R E E _ F N * * The global NS binding->ns_specific free function. The NS init routine * inits this. It's purpose is to prevent the runtime from always pulling * in the name service modules when they're not necessary. */ GLOBAL rpc_g_ns_specific_free_fn_t rpc_g_ns_specific_free_fn = NULL; /* This table is used only by comtwrref.c to validate towers, but we need * it accessible by the dynamic loading code so that new modules can register * with the runtime. * We allocate extra space, since there may be mulitple entries: eg * rpc_c_protseq_id_ncacn_osi_dna * */ GLOBAL unsigned32 rpc_g_tower_prot_id_number = 0; /* number of elts in rpc_g_tower_prot_ids */ GLOBAL rpc_tower_prot_ids_t rpc_g_tower_prot_ids[RPC_C_PROTSEQ_ID_MAX*2] = { #if 0 { rpc_c_protseq_id_ncacn_ip_tcp, 3, { {0x0B, { 0, 0, 0, 0, 0, {0} }}, {0x07, { 0, 0, 0, 0, 0, {0} }}, {0x09, { 0, 0, 0, 0, 0, {0} }}, {0x00, { 0, 0, 0, 0, 0, {0} }} } }, { rpc_c_protseq_id_ncacn_dnet_nsp, 4, { {0x0B, { 0, 0, 0, 0, 0, {0} }}, {0x02, { 0, 0, 0, 0, 0, {0} }}, {0x04, { 0, 0, 0, 0, 0, {0} }}, {0x06, { 0, 0, 0, 0, 0, {0} }} } }, { rpc_c_protseq_id_ncacn_osi_dna, 4, { {0x0B, { 0, 0, 0, 0, 0, {0} }}, {0x03, { 0, 0, 0, 0, 0, {0} }}, {0x04, { 0, 0, 0, 0, 0, {0} }}, {0x06, { 0, 0, 0, 0, 0, {0} }} } }, { rpc_c_protseq_id_ncacn_osi_dna, 4, { {0x0B, { 0, 0, 0, 0, 0, {0} }}, {0x03, { 0, 0, 0, 0, 0, {0} }}, {0x05, { 0, 0, 0, 0, 0, {0} }}, {0x06, { 0, 0, 0, 0, 0, {0} }} } }, { rpc_c_protseq_id_ncadg_ip_udp, 3, { {0x0A, { 0, 0, 0, 0, 0, {0} }}, {0x08, { 0, 0, 0, 0, 0, {0} }}, {0x09, { 0, 0, 0, 0, 0, {0} }}, {0x00, { 0, 0, 0, 0, 0, {0} }} } }, { rpc_c_protseq_id_ncadg_dds, 3, { {0x0A, { 0, 0, 0, 0, 0, {0} }}, {0x0D, {0x9865a080UL, 0xbb73, 0x11c9, 0x96, 0x3c, {0x08,0x00, 0x2b, 0x13, 0xec, 0x4e}}}, {0x0D, {0x9b86b6a0UL, 0xbb73, 0x11c9, 0xb8, 0x89, {0x08, 0x00, 0x2b, 0x13, 0xec, 0x4e}}}, {0x00, { 0, 0, 0, 0, 0, {0} }} } } #endif }; /***********************************************************************/ /* * R P C _ G _ P R O T S E Q _ I D * * The RPC Protocol Sequence ID table. This table is indexed by an RPC * Protocol Sequence ID. * * An RPC Protocol Sequence represents a specific RPC Protocol/Network * Address Family combination which is by definition a valid combination * of protocols. An RPC Protocol Sequence also represents a specific * NAF interface type, since there may be multiple within a NAF. Each * RPC Protocol Sequence has an entry in this table. * * Note that the ".rpc_protseq_id" field of i'th element in the table * is always "i". While redundant, this is useful so that you can pass * pointers to individual table elements. * * The fields are: * * supported A boolean flag initialized to zero and filled * in by rpc__init if it determines that this Protocol * Sequence is actually supported by the system. * * rpc_protseq_id A constant identifier for the Protocol Sequence. * * rpc_protocol_id A constant identifier for the RPC Protocol used * in this Protocol Sequence. * * naf_id A constant identifier for the Network Address * Family used in this Protocol Sequence. * * net_protocol_id A constant identifier for the network protocol * used in this Protocol Sequence. * * net_if_id A constant identifier for the network interface * type used in this Protocol Sequence. * * rpc_protseq A string constant defining this Protocol Sequence. * * port_restriction_list_p * An optionally pointer to a port_restriction_list * object. */ GLOBAL rpc_protseq_id_elt_t rpc_g_protseq_id[RPC_C_PROTSEQ_ID_MAX] = { #if 0 { /* Connection-RPC / IP / TCP */ 0, rpc_c_protseq_id_ncacn_ip_tcp, RPC_C_PROTOCOL_ID_NCACN, RPC_C_NAF_ID_IP, RPC_C_NETWORK_PROTOCOL_ID_TCP, RPC_C_NETWORK_IF_ID_STREAM, RPC_PROTSEQ_NCACN_IP_TCP, (rpc_port_restriction_list_p_t) NULL }, { /* Connection-RPC / DECnet / NSP */ 0, rpc_c_protseq_id_ncacn_dnet_nsp, RPC_C_PROTOCOL_ID_NCACN, RPC_C_NAF_ID_DNET, RPC_C_NETWORK_PROTOCOL_ID_UNS, RPC_C_NETWORK_IF_ID_STREAM, RPC_PROTSEQ_NCACN_DNET_NSP, (rpc_port_restriction_list_p_t) NULL }, { /* Connection-RPC / OSI / DNASESSION */ 0, rpc_c_protseq_id_ncacn_osi_dna, RPC_C_PROTOCOL_ID_NCACN, RPC_C_NAF_ID_OSI, RPC_C_NETWORK_PROTOCOL_ID_DNASESSION, RPC_C_NETWORK_IF_ID_SEQPACKET, RPC_PROTSEQ_NCACN_OSI_DNA, (rpc_port_restriction_list_p_t) NULL }, { /* Datagram-RPC / IP / UDP */ 0, rpc_c_protseq_id_ncadg_ip_udp, RPC_C_PROTOCOL_ID_NCADG, RPC_C_NAF_ID_IP, RPC_C_NETWORK_PROTOCOL_ID_UDP, RPC_C_NETWORK_IF_ID_DGRAM, RPC_PROTSEQ_NCADG_IP_UDP, (rpc_port_restriction_list_p_t) NULL }, { /* Datagram-RPC / DDS */ 0, rpc_c_protseq_id_ncadg_dds, RPC_C_PROTOCOL_ID_NCADG, RPC_C_NAF_ID_DDS, RPC_C_NETWORK_PROTOCOL_ID_DDS, RPC_C_NETWORK_IF_ID_DGRAM, RPC_PROTSEQ_NCADG_DDS, (rpc_port_restriction_list_p_t) NULL #ifdef TEST_PROTOCOL }, { /* Test-RPC / IP / TCP */ 0, RPC_C_PROTSEQ_ID_NCATP_IP_TCP, RPC_C_PROTOCOL_ID_NCATP, RPC_C_NAF_ID_IP, RPC_C_NETWORK_PROTOCOL_ID_TCP, RPC_C_NETWORK_IF_ID_STREAM, RPC_PROTSEQ_NCATP_IP_TCP, (rpc_port_restriction_list_p_t) NULL #endif /* TEST_PROTOCOL */ } #endif }; /***********************************************************************/ /* * R P C _ G _ P R O T O C O L _ I D * * The RPC Protocol ID table. Each RPC Protocol has an entry in this * table. This table is index by RPC Protocol ID. * * Note that the ".rpc_protocol_id" field of i'th element in the table * is always "i". While redundant, this is useful so that you can pass * pointers to individual table elements. * * The fields are: * * prot_init The address of an initialization routine in the * Protocol Service that will be called by rpc__init. * * prot_fork_handler The address of a routine to call to handle * protocol specific, fork-related processing. * * rpc_protocol_id A constant identifier for this RPC Protocol. * * call_epv An entry point vector for the Call Services in * the Protocol Service. * * mgmt_epv An entry point vector for the Management Services in * the Protocol Service. * * binding_epv An entry point vector for the Binding Services * in the Protocol Service. * * network_epv An entry point vector for the Network Services * in the Protocol Service. */ GLOBAL rpc_protocol_id_elt_t rpc_g_protocol_id[RPC_C_PROTOCOL_ID_MAX] = { #if 0 #ifdef PROT_NCACN { rpc__ncacn_init, /* Connection-RPC */ NULL, RPC_C_PROTOCOL_ID_NCACN, NULL, NULL, NULL, NULL }, #else {NULL}, #endif #ifdef PROT_NCADG { rpc__ncadg_init, /* Datagram-RPC */ NULL, RPC_C_PROTOCOL_ID_NCADG, NULL, NULL, NULL, NULL } #else {NULL} #endif #ifdef PROT_NCATP ,{ rpc__ncatp_init, /* Test-RPC */ NULL, RPC_C_PROTOCOL_ID_NCATP, NULL, NULL, NULL, NULL } #endif #endif }; /***********************************************************************/ /* * R P C _ G _ N A F _ I D * * The Network Address Family ID table. This table is indexed by a NAF * ID. * * Each Network Address Family Extension has an entry in this table. * Note that this is a sparse table because it uses the Unix Address * Family ID's as NAF ID's. * * Note that the ".naf_id" field of i'th element in the table is always * "i". While redundant, this is useful so that you can pass pointers * to individual table elements. * * The fields are: * * naf_init The address of an initialization routine in the * NAF Service that will be called by rpc__init * * naf_id A constant identifier for this NAF. * * net_if_id A constant identifier for the network interface * type used in the NAF initialization routine (when * determining if this NAF is supported). * * naf_epv An entry point vector for the NAF Service. */ GLOBAL rpc_naf_id_elt_t rpc_g_naf_id[RPC_C_NAF_ID_MAX] = { #if 0 {NULL, 0, 0, NULL}, {NULL, 0, 0, NULL}, #ifdef NAF_IP_STATIC { rpc__ip_init, RPC_C_NAF_ID_IP, RPC_C_NETWORK_IF_ID_DGRAM, NULL }, #else {NULL, 0, 0, NULL}, #endif {NULL, 0, 0, NULL}, {NULL, 0, 0, NULL}, {NULL, 0, 0, NULL}, {NULL, 0, 0, NULL}, {NULL, 0, 0, NULL}, {NULL, 0, 0, NULL}, {NULL, 0, 0, NULL}, {NULL, 0, 0, NULL}, {NULL, 0, 0, NULL}, #ifdef NAF_DNET_STATIC { rpc__dnet_init, RPC_C_NAF_ID_DNET, RPC_C_NETWORK_IF_ID_SEQPACKET, NULL }, #else {NULL, 0, 0, NULL}, #endif #ifdef NAF_DDS_STATIC { rpc__dds_init, RPC_C_NAF_ID_DDS, RPC_C_NETWORK_IF_ID_DGRAM, NULL }, #else {NULL, 0, 0, NULL}, #endif {NULL, 0, 0, NULL}, {NULL, 0, 0, NULL}, {NULL, 0, 0, NULL}, {NULL, 0, 0, NULL}, {NULL, 0, 0, NULL}, #ifdef NAF_OSI_STATIC { rpc__osi_init, RPC_C_NAF_ID_OSI, RPC_C_NETWORK_IF_ID_STREAM, NULL } #else {NULL, 0, 0, NULL} #endif #endif }; /***********************************************************************/ /* * R P C _ G _ A U T H N _ P R O T O C O L _ I D * * The RPC Authentication Protocol ID table. * * Each RPC Authentication protocol has an entry in this table. These * entries include the following fields: * * auth_init The address of an initialization routine in the * Authentication Service that will be called by * rpc__init. * * authn_protocol_id A constant identifier for this Authentication Service. * * dce_rpc_authn_protocol_id_t * The value that goes into RPC protocol messages to * identify which authentication protocol is in use. * * epv An entry point vector for the Authentication Service * functions. * * Note that the ".authn_protocol_id" field of i'th element in the table * is always "i". While redundant, this is useful so that you can pass * pointers to individual table elements. * * Note that the ".auth_protocol_id" contains API values (see * "rpc_c_authn_..." constants in "rpc.idl"). * "dce_rpc_authn_protocol_id_t" contains architectural values that appear * in network messages (see "dce_c_rpc_authn_protocol_..." constants in * "nbase.idl"). */ /* FreeDCE Note: All auth modules are DSOs loaded via rpc__load_modules by rpc__init */ GLOBAL rpc_authn_protocol_id_elt_t rpc_g_authn_protocol_id[RPC_C_AUTHN_PROTOCOL_ID_MAX] = { #if 0 { /* 0 */ NULL, rpc_c_authn_none, dce_c_rpc_authn_protocol_none, NULL, NULL } , { /* 1 */ NULL, rpc_c_authn_dce_private, dce_c_rpc_authn_protocol_krb5, NULL, NULL }, { /* 2 (reserved for dce_public) */ NULL, rpc_c_authn_dce_public, /* dce_c_rpc_authn_protocol_... */ 0, NULL, NULL }, { /* 3 */ NULL, rpc_c_authn_dce_dummy, dce_c_rpc_authn_protocol_dummy, NULL, NULL }, { /* 4 (reserved for dssa_public) */ NULL, rpc_c_authn_dssa_public, 0, NULL, NULL } #endif };