/* * * (c) Copyright 1990 OPEN SOFTWARE FOUNDATION, INC. * (c) Copyright 1990 HEWLETT-PACKARD COMPANY * (c) Copyright 1990 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. * */ /* */ /* ** ** ** NAME: ** ** COMTWRREF.C ** ** FACILITY: ** ** Remote procedure call (RPC) ** ** ABSTRACT: ** ** Set of routines supporting operations on the runtime reference ** represention of protocol towers. ** ** ** **/ #include /* Common internals for RPC Runtime system */ #include /* Externals for Common Services component */ #include /* Privates for Common Services component */ #include /* Private prototypes of this module */ #include /* tower defs for other RPC components */ #include /* Privates for the Tower floor services */ /* **++ ** ROUTINE NAME: rpc__tower_ref_add_floor ** ** SCOPE: PRIVATE - declared in comtwrref.h ** ** DESCRIPTION: ** ** Adds a floor to a tower reference. ** ** INPUTS: ** floor_number The number of the floor to add to the tower. ** floor The tower floor to add to the tower. ** tower_ref The tower to which the floor is added. ** ** INPUT/OUTPUTS: none ** ** OUTPUTS: ** ** status Returns the status code from the tower add floor ** operation. This status code is a value that ** indicates whether the routine completed ** successfully and, if not, why. ** Returns rpc_s_ok. ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: void ** ** SIDE EFFECTS: none ** **-- */ PRIVATE void rpc__tower_ref_add_floor #ifdef _DCE_PROTO_ ( unsigned32 floor_number, rpc_tower_floor_p_t floor, rpc_tower_ref_t *tower_ref, unsigned32 *status ) #else (floor_number, floor, tower_ref, status) unsigned32 floor_number; rpc_tower_floor_p_t floor; rpc_tower_ref_t *tower_ref; unsigned32 *status; #endif { CODING_ERROR (status); /* * If we're replacing the floor, free it first. */ if (tower_ref->floor[floor_number-1] != NULL) { rpc__tower_flr_free (&(tower_ref->floor[floor_number-1]), status); if (*status != rpc_s_ok) { return; } } /* * Add the new floor. */ tower_ref->floor[floor_number-1] = floor; *status = rpc_s_ok; return; } /* **++ ** ROUTINE NAME: rpc__tower_ref_alloc ** ** SCOPE: PRIVATE - declared in comtwrref.h ** ** DESCRIPTION: ** ** Allocates memory for a RPC tower reference structure and initializes ** the structure to point to the individual floors in the tower. ** The returned referenced structure contains NULL floor pointers ** for any unused floor. ** ** INPUTS: ** ** tower_octet_string Canonical tower to reference using a tower ** reference structure. ** ** num_flrs Specifies the total number of floors to be stored ** in the returned tower reference argument. ** ** start_flr Tower floor number of the first floor in ** tower_octet_string. ** ** INPUT/OUTPUTS: none ** ** OUTPUTS: ** tower_ref The returned uninitialized RPC tower reference. ** ** status Returns the status code from the tower ref allocate ** operation. This status code is a value that indicates ** whether the routine completed successfully and, ** if not, why. Returns: ** rpc_s_ok ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: void ** ** SIDE EFFECTS: none ** **-- */ PRIVATE void rpc__tower_ref_alloc #ifdef _DCE_PROTO_ ( byte_p_t tower_octet_string, unsigned32 num_flrs, unsigned32 start_flr, rpc_tower_ref_p_t *tower_ref, unsigned32 *status ) #else (tower_octet_string, num_flrs, start_flr, tower_ref, status) byte_p_t tower_octet_string; unsigned32 num_flrs; unsigned32 start_flr; rpc_tower_ref_p_t *tower_ref; unsigned32 *status; #endif { byte_p_t tower_floor; unsigned32 i; CODING_ERROR (status); /* * Allocate the tower reference structure allowing * for the number of tower floors desired. * * Note, the first floor is allocated via the "floor[1] * member of rpc_tower_ref_t. */ RPC_MEM_ALLOC ( *tower_ref, rpc_tower_ref_p_t, sizeof (rpc_tower_ref_t) + (sizeof (rpc_tower_floor_p_t) * (num_flrs-1)), RPC_C_MEM_TOWER_REF, RPC_C_MEM_WAITOK); /* * Initialize floor count to the number of floors and * floor pointers to NULL. */ (*tower_ref)->count = num_flrs; for (i=0; i < num_flrs; i++) { (*tower_ref)->floor[i] = NULL; } /* * Initialize local to point to beginning of * the canonical tower floor. */ tower_floor = tower_octet_string + RPC_C_TOWER_FLR_COUNT_SIZE; /* * For each tower floor, starting at the desired floor, * allocate the floor and initialize with the information * in the tower structure. */ for (i= start_flr-1; i < num_flrs; i++) { /* * Allocate the tower floor */ RPC_MEM_ALLOC ( (*tower_ref)->floor[i], rpc_tower_floor_p_t, sizeof (rpc_tower_floor_t), RPC_C_MEM_TOWER_FLOOR, RPC_C_MEM_WAITOK ); /* * Initialize the floor's tower octet free flag to not * free the tower floor octet string, since they will be * freed by the caller who created them. */ (*tower_ref)->floor[i]->free_twr_octet_flag = false; /* * Get the pointer to the octet string. */ (*tower_ref)->floor[i]->octet_string = tower_floor; /* * Get the protocol identifier count. */ memcpy ((char *) &((*tower_ref)->floor[i]->prot_id_count), (char *) tower_floor, RPC_C_TOWER_FLR_LHS_COUNT_SIZE); /* * Convert prot id count to host's endian representation. */ RPC_RESOLVE_ENDIAN_INT16 ((*tower_ref)->floor[i]->prot_id_count); /* * Get the additional information count. */ memcpy ((char *) &((*tower_ref)->floor[i]->address_count), (char *) tower_floor + RPC_C_TOWER_FLR_LHS_COUNT_SIZE + (*tower_ref)->floor[i]->prot_id_count, RPC_C_TOWER_FLR_RHS_COUNT_SIZE); /* * Convert address count to host's endian representation. */ RPC_RESOLVE_ENDIAN_INT16 ((*tower_ref)->floor[i]->address_count); /* * Point to the next tower floor in the tower octet string. */ tower_floor += RPC_C_TOWER_FLR_LHS_COUNT_SIZE + (*tower_ref)->floor[i]->prot_id_count + RPC_C_TOWER_FLR_RHS_COUNT_SIZE + (*tower_ref)->floor[i]->address_count; } *status = rpc_s_ok; return; } /* **++ ** ROUTINE NAME: rpc__tower_ref_copy ** ** SCOPE: PRIVATE - declared in comtwrref.h ** ** DESCRIPTION: ** ** Allocates memory for a RPC tower reference structure and ** copies the contents of the source tower reference into it. ** The new tower reference points to the same tower floor as ** the source data structure. The new tower reference free floor ** flag is set to false so that a call to free the tower reference ** will not attempt to deallocate the tower floor twice. ** ** INPUTS: ** ** source_tower RPC tower reference to copy. ** ** INPUT/OUTPUTS: none ** ** OUTPUTS: ** ** dest_tower Returns a tower reference which is a copy of ** source_tower. ** ** status Returns the status code from the tower ref copy ** operation. This status code is a value that ** indicates whether the routine completed ** successfully and, if not, why. ** Returns rpc_s_ok. ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: void ** ** SIDE EFFECTS: none ** **-- */ PRIVATE void rpc__tower_ref_copy #ifdef _DCE_PROTO_ ( rpc_tower_ref_p_t source_tower, rpc_tower_ref_p_t *dest_tower, unsigned32 *status ) #else (source_tower, dest_tower, status) rpc_tower_ref_p_t source_tower; rpc_tower_ref_p_t *dest_tower; unsigned32 *status; #endif { unsigned32 i, tower_ref_size; CODING_ERROR (status); tower_ref_size = sizeof (rpc_tower_ref_t) + (sizeof (rpc_tower_floor_p_t) * ((source_tower->count)-1)); /* * Allocate the destination tower structure and * copy the source tower into it. */ RPC_MEM_ALLOC ( *dest_tower, rpc_tower_ref_p_t, tower_ref_size, RPC_C_MEM_TOWER_REF, RPC_C_MEM_WAITOK); /* * Copy the floor count to the destination tower ref. */ (*dest_tower)->count = source_tower->count; /* * For each floor in the source tower ref, allocate a new floor * for the destination tower ref and copy the floor contents. * Set the destination free flag to false since the * floors' tower octet string will be freed when freeing * the source_tower. */ for (i=0; i < source_tower->count; i++) { RPC_MEM_ALLOC ( (*dest_tower)->floor[i], rpc_tower_floor_p_t, sizeof (rpc_tower_floor_t), RPC_C_MEM_TOWER_FLOOR, RPC_C_MEM_WAITOK); memcpy ((*dest_tower)->floor[i], source_tower->floor[i], sizeof (rpc_tower_floor_t)); (*dest_tower)->floor[i]->free_twr_octet_flag = false; } *status = rpc_s_ok; return; } /* **++ ** ROUTINE NAME: rpc__tower_ref_free ** ** SCOPE: PRIVATE - declared in comtwrref.h ** ** DESCRIPTION: ** ** Releases memory associated with a tower reference, including the ** tower floor as well as the tower reference. ** ** INPUTS: none ** ** ** INPUT/OUTPUTS: ** ** tower_ref The tower reference to free. Nulled on return. ** ** OUTPUTS: ** ** status Returns the status code from the tower ref free ** operation. This status code is a value that ** indicates whether the routine completed ** successfully and, if not, why. ** Returns rpc_s_ok. ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: void ** ** SIDE EFFECTS: none ** **-- */ PRIVATE void rpc__tower_ref_free #ifdef _DCE_PROTO_ ( rpc_tower_ref_p_t *tower_ref, unsigned32 *status ) #else (tower_ref, status) rpc_tower_ref_p_t *tower_ref; unsigned32 *status; #endif { unsigned32 i; CODING_ERROR (status); /* * Free the tower floors in the tower, freeing the octet string * associated with the each floor only if the free floor flag is set. */ for (i=0; i < (*tower_ref)->count; i++) { rpc__tower_flr_free (&((*tower_ref)->floor[i]), status); if (*status != rpc_s_ok) { return; } } /* * Free the tower reference and set the pointer to NULL. */ RPC_MEM_FREE (*tower_ref, RPC_C_MEM_TOWER_REF); *tower_ref = NULL; *status = rpc_s_ok; return; } /* **++ ** ROUTINE NAME: rpc__tower_ref_inq_protseq_id ** ** SCOPE: PRIVATE - declared in comtwrref.h ** ** DESCRIPTION: ** ** Returns the RPC protocol sequence from a tower reference. ** ** INPUTS: ** ** tower_ref Protocol tower reference from which to ** return the RPC protocol sequence id. ** ** INPUT/OUTPUTS: none ** ** OUTPUTS: ** ** protseq_id Returns the protocol sequence id for tower_ref. ** ** status Returns the status code from the inquire protocol ** sequence operation. This status code is a value that ** indicates whether the routine completed ** successfully and, if not, why. ** Returns: ** rpc_s_ok ** rpc_s_not_rpc_tower ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: void ** ** SIDE EFFECTS: none ** **-- */ PRIVATE void rpc__tower_ref_inq_protseq_id #ifdef _DCE_PROTO_ ( rpc_tower_ref_p_t tower_ref, rpc_protseq_id_t *protseq_id, unsigned32 *status ) #else (tower_ref, protseq_id, status) rpc_tower_ref_p_t tower_ref; rpc_protseq_id_t *protseq_id; unsigned32 *status; #endif { boolean match; rpc_flr_prot_id_t *tower_prot_ids, master_prot_ids[RPC_C_MAX_NUM_NETWORK_FLOORS + 1]; byte_p_t tp; unsigned32 floors_to_search, start_floor, i, j, k; rpc_protocol_id_t rpc_protocol_id; unsigned32 version_major; unsigned32 version_minor; CODING_ERROR (status); /* * Initialize return protseq in case of failure. */ *protseq_id = RPC_C_INVALID_PROTSEQ_ID; /* * Let's find out if this is a tower without floors 1 & 2 (CDS * has been known to use towers like this). So long as the tower * contains an RPC protocol (floor 3) and recognized addressing * floors, we'll try to figure out its protseq id. */ /* * Check to see if this is a full tower. */ if (tower_ref->count >= RPC_C_FULL_TOWER_MIN_FLR_COUNT) { /* * Calculate the number of floors we are searching. * This is the number of lower tower floors plus one for floor 3. */ floors_to_search = (tower_ref->count - RPC_C_NUM_RPC_FLOORS)+ 1; /* * For a full rpc tower, identifying the protseq begins at the * rpc protocol id floor. */ start_floor = RPC_C_NUM_RPC_FLOORS - 1; } else { /* * Check to see if this is a minimal tower. */ if (tower_ref->count >= RPC_C_MIN_TOWER_MIN_FLR_COUNT) { /* * We might have a minimal rpc tower. Let's make sure the 1st floor * in the tower contains a valid rpc protocol. */ rpc__tower_flr_to_rpc_prot_id (tower_ref->floor[0], &rpc_protocol_id, &version_major, &version_minor, status); /* * If the floor contains a valid rpc protocol id, we have a minimal * rpc tower and need to process all of the floors. */ if (*status == rpc_s_ok) { floors_to_search = tower_ref->count; start_floor = 0; } else { /* * We don't have even a minimal rpc tower. */ *status = rpc_s_not_rpc_tower; return; } } else { *status = rpc_s_not_rpc_tower; return; } } /* * Allocate the array to hold the tower's protocol ids. * This is one element for each of the lower tower floors plus * an element for the the RPC protocol id floor (in a minimal tower * floor 1; in a full tower floor 3). */ RPC_MEM_ALLOC ( tower_prot_ids, rpc_flr_prot_id_p_t, floors_to_search * sizeof (rpc_flr_prot_id_t), RPC_C_MEM_TOWER_PROT_IDS, RPC_C_MEM_WAITOK); /* * Copy the tower floors' protocol id, starting at the * RPC protocol id, into the tower_prot_ids array. */ for (i= 0, j= start_floor; i < floors_to_search; i++) { /* * Copy the floor's protocol id prefix. */ memcpy ((char *) &(tower_prot_ids[i].prefix), (char *) RPC_PROT_ID_START(tower_ref->floor[i+j]), RPC_C_TOWER_PROT_ID_SIZE); /* * If the floor's protocol id also has an uuid, * copy it. */ if (tower_ref->floor[i+j]->prot_id_count > RPC_C_TOWER_PROT_ID_SIZE) { tp = (byte_p_t) RPC_PROT_ID_START(tower_ref->floor[i+j]); memcpy ((char *) &(tower_prot_ids[i].uuid), (char *) (tp + RPC_C_TOWER_PROT_ID_SIZE), RPC_C_TOWER_UUID_SIZE); RPC_RESOLVE_ENDIAN_UUID (tower_prot_ids[i].uuid); } else { tower_prot_ids[i].uuid = uuid_g_nil_uuid; } } /* * For each protocol sequence supported by RPC, * see if the tower protocol ids match. * * Note, we use RPC_C_PROTSEQ_ID_MAX+1 since * there are two entries in our table for * RPC_C_PROTSEQ_ID_NCACN_OSI_DNA - one for nsp * and the other for tp4. */ for (i = 0; i < rpc_g_tower_prot_id_number; i++) { /* * If the number of floors to process does not * match the number of floors for this protocol * sequence, skip it. */ if (floors_to_search != rpc_g_tower_prot_ids[i].num_floors) { continue; } /* * Copy the protocol id for the current * protocol sequence being matched into * a local array. Do this for the number * of floors in this protocol sequence. */ for (k = 0; k < rpc_g_tower_prot_ids[i].num_floors; k++) { master_prot_ids[k].prefix = rpc_g_tower_prot_ids[i].floor_prot_ids[k].prefix; master_prot_ids[k].uuid = rpc_g_tower_prot_ids[i].floor_prot_ids[k].uuid; } /* * For each protocol id in the master array, * see if a match is found with the tower floors' protocol ids. * We only compare to the number of significant floors. */ /* * Assume success. This way we can check the status * of uuid_equal when it is called. */ *status = rpc_s_ok; for (k = 0; k < rpc_g_tower_prot_ids[i].num_floors; k++) { for (j = 0; j < floors_to_search; j++) { if ((master_prot_ids[k].prefix == tower_prot_ids[j].prefix) && (uuid_equal (&(master_prot_ids[k].uuid), &(tower_prot_ids[j].uuid), status))) { master_prot_ids[k].prefix = 0; break; } /* * Check status from uuid_equal. * Return if failure. */ if (*status != rpc_s_ok) { goto CLEANUP; } } } /* * See if a match was found */ for (k = 0, match = true; k < rpc_g_tower_prot_ids[i].num_floors; k++) { if (master_prot_ids[k].prefix != 0) { match = false; break; } } if (match) { *protseq_id = rpc_g_tower_prot_ids[i].rpc_protseq_id; /* * Status is already set above. */ goto CLEANUP; } } /* * If we get here, then we couldn't find a match and must * assume that the tower does not belong to RPC. */ *status = rpc_s_not_rpc_tower; CLEANUP: /* * Free the allocated array of the tower floors * protocol identifier. */ RPC_MEM_FREE (tower_prot_ids, RPC_C_MEM_TOWER_PROT_IDS); /* * Return with the protocol id sequence and status. */ return; } /* **++ ** ROUTINE NAME: rpc__tower_ref_is_compatible ** ** SCOPE: PRIVATE - declared in comtwrref.h ** ** DESCRIPTION: ** ** Tells whether the specified protocol tower is compatible with ** the client's protocols. ** ** INPUTS: ** ** if_spec The interface specification for the client. ** If NULL, the if_spec compatibility check is bypassed. ** ** tower_ref Protocol tower reference to be checked for ** compatibility with the client. ** ** INPUT/OUTPUTS: none ** ** OUTPUTS: ** ** status Returns the status code from the tower-is-compatible ** operation. This status code is a value that ** indicates whether the routine completed ** successfully and, if not, why. ** Returns ** rpc_s_ok ** or status from a called routine. ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: ** ** true The specified protocol tower is compatible ** with the client's protocols. ** false The specified protocol tower is NOT compatible ** with the client's protocols. ** ** SIDE EFFECTS: none ** **-- */ PRIVATE boolean rpc__tower_ref_is_compatible #ifdef _DCE_PROTO_ ( rpc_if_rep_p_t if_spec, rpc_tower_ref_p_t tower_ref, unsigned32 *status ) #else (if_spec, tower_ref, status) rpc_if_rep_p_t if_spec; rpc_tower_ref_p_t tower_ref; unsigned32 *status; #endif { boolean match; unsigned32 if_spec_syntax_count, tower_vers_major, tower_vers_minor, version_major, version_minor; rpc_if_id_t if_id, tower_if_id; rpc_syntax_id_t *if_syntax_id, tower_syntax_id; rpc_protseq_id_t tower_protseq_id; rpc_protocol_id_t tower_prot_id; unsigned8 temp_id; CODING_ERROR (status); /* * Obtain the protocol sequence from this tower. */ rpc__tower_ref_inq_protseq_id (tower_ref, &tower_protseq_id, status); if (*status != rpc_s_ok) { *status = rpc_s_ok; /* ignore towers we don't understand */ return (false); } /* * Ensure the protocol sequence from the tower * is supported by this client. */ if (!(RPC_PROTSEQ_INQ_SUPPORTED (tower_protseq_id))) { /* * Invalid protocol sequence, return status from call. */ return (false); } /* * We have a valid protocol sequence. * Check the interface for compatibility if one is specified. */ if (if_spec != NULL) { /* * Get the interface identifier. */ rpc_if_inq_id ((rpc_if_handle_t) if_spec, &if_id, status); if (*status != rpc_s_ok) { return (false); } /* * Get the interface identifier from the tower */ rpc__tower_flr_to_if_id (tower_ref->floor[0], &tower_if_id, status); if (*status != rpc_s_ok) { return (false); } /* * Compare the client's interface identifier to the * tower's interface id. (Checks both the uuid and version.) */ if (!(rpc__if_id_compare (&if_id, &tower_if_id, rpc_c_vers_compatible, status))) { return (false); } /* * See if any of the if_spec transfer syntaxes matches * the tower transfer syntaxes. * * Note an interface transfer syntax count of 0 is an internal error. */ /* * Obtain the tower transfer syntax. */ rpc__tower_flr_to_drep (tower_ref->floor[1], &tower_syntax_id, status); if (*status != rpc_s_ok) { return (false); } for (if_spec_syntax_count = 0, match = false, if_syntax_id = if_spec->syntax_vector.syntax_id; ((match == false) && (if_spec_syntax_count < if_spec->syntax_vector.count )); if_spec_syntax_count++, if_syntax_id++ ) { /* * Check if a syntax id and version match. */ match = uuid_equal (&(tower_syntax_id.id), &(if_syntax_id->id), status); if ((match == true) && (tower_syntax_id.version != if_syntax_id->version)) { match = false; } } /* * if no match occurred, binding is not compatible - return false */ if (match == false) { *status = rpc_s_ok; return (false); } } /* * Obtain the RPC protocol id and version numbers of the tower. */ rpc__tower_flr_to_rpc_prot_id (tower_ref->floor[2], &tower_prot_id, &tower_vers_major, &tower_vers_minor, status); if (*status != rpc_s_ok) { return (false); } /* * Obtain the clients' version numbers for the protocol sequence * specified in the tower. */ rpc__network_inq_prot_version ( tower_protseq_id, &temp_id, &version_major, &version_minor, status); if (*status != rpc_s_ok) { return (false); } /* * Compare protocol versions, they are only 1 byte each. */ if ((unsigned8) version_major != (unsigned8) tower_vers_major) /* * We don't do this so we can rev the minor protocol version. * || ((unsigned8) version_minor > (unsigned8) tower_vers_minor) */ { return (false); } /* * Tower is compatible with the client's. */ return (true); } /* **++ ** ROUTINE NAME: rpc__tower_ref_vec_free ** ** SCOPE: PRIVATE - declared in comtwrref.h ** ** DESCRIPTION: ** ** Releases memory associated with a tower reference vector, ** including the towers as well as the vector. ** ** INPUTS: none ** ** INPUT/OUTPUTS: ** ** tower_vector The tower vector to free. Nulled on return. ** ** OUTPUTS: ** ** status Returns the status code from the tower free ** operation. This status code is a value that ** indicates whether the routine completed ** successfully and, if not, why. ** Returns ** rpc_s_ok ** or status from a called routine. ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: void ** ** SIDE EFFECTS: none ** **-- */ PRIVATE void rpc__tower_ref_vec_free #ifdef _DCE_PROTO_ ( rpc_tower_ref_vector_p_t *tower_vector, unsigned32 *status ) #else (tower_vector, status) rpc_tower_ref_vector_p_t *tower_vector; unsigned32 *status; #endif { unsigned32 i; CODING_ERROR (status); /* * Free the tower vector's lower network floors. */ rpc__tower_free (&((*tower_vector)->lower_flrs), status); if (*status != rpc_s_ok) { return; } /* * Free each tower reference in the vector. */ for (i=0; i < (*tower_vector)->count; i++) { rpc__tower_ref_free (&((*tower_vector)->tower[i]), status); if (*status != rpc_s_ok) { return; } } /* * Free the tower vector structure and set pointer to NULL. */ RPC_MEM_FREE (*tower_vector, RPC_C_MEM_TOWER_REF_VECTOR); *tower_vector = NULL; *status = rpc_s_ok; return; } /* **++ ** ROUTINE NAME: rpc__tower_ref_vec_from_binding ** ** SCOPE: PRIVATE - declared in comtwrref.h ** ** DESCRIPTION: ** ** Creates a vector of tower references from a single binding handle. ** A separate tower reference is created for each data representation ** (transfer syntax) found in the interface specification. ** With the exception of the data representation floor, each of ** the returned towers in the vector is identical. ** ** INPUTS: ** ** if_spec Interface specification. ** binding Binding handle. ** ** INPUT/OUTPUTS: none. ** ** ** OUTPUTS: ** ** tower_vector Returns a pointer to a tower reference vector. ** ** status Returns the status code from the tower-ref vector ** from binding operation. This status code is a value ** that indicates whether the routine completed ** successfully and, if not, why. ** Returns ** rpc_s_ok ** or status from a called routine. ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: void ** ** SIDE EFFECTS: none ** **-- */ PRIVATE void rpc__tower_ref_vec_from_binding #ifdef _DCE_PROTO_ ( rpc_if_rep_p_t if_spec, rpc_binding_handle_t binding, rpc_tower_ref_vector_p_t *tower_vector, unsigned32 *status ) #else (if_spec, binding, tower_vector, status) rpc_if_rep_p_t if_spec; rpc_binding_handle_t binding; rpc_tower_ref_vector_p_t *tower_vector; unsigned32 *status; #endif { unsigned16 lower_flr_count; unsigned32 i, temp_status; twr_p_t lower_floors; rpc_tower_ref_p_t tower_copy; rpc_tower_floor_p_t tower_floor; rpc_if_id_t if_id; rpc_binding_rep_p_t binding_rep; rpc_syntax_id_t *if_syntax_id; CODING_ERROR (status); /* * Create the tower vector. */ RPC_MEM_ALLOC ( *tower_vector, rpc_tower_ref_vector_p_t, sizeof (rpc_tower_ref_vector_t) + ((if_spec->syntax_vector.count -1) * (sizeof (rpc_tower_ref_p_t))) , RPC_C_MEM_TOWER_REF_VECTOR, RPC_C_MEM_WAITOK ); /* * Initialize tower count. */ (*tower_vector)->count = 0; /* * Create the tower for the first transfer syntax * in the interface specification. */ /* * Obtain the rpc address of this binding. */ binding_rep = (rpc_binding_rep_p_t) binding; /* * Create the lower tower floors. */ rpc__naf_tower_flrs_from_addr ( binding_rep->rpc_addr, &lower_floors, status); if (*status != rpc_s_ok) { RPC_MEM_FREE (*tower_vector, RPC_C_MEM_TOWER_REF_VECTOR); return; } /* * Initialize the tower vector with the pointer * to the lower floors. */ (*tower_vector)->lower_flrs = lower_floors; /* * Get the number of lower tower floors returned and * convert to host's representation. */ memcpy ((char *)&lower_flr_count, (char *)lower_floors->tower_octet_string, RPC_C_TOWER_FLR_COUNT_SIZE); RPC_RESOLVE_ENDIAN_INT16 (lower_flr_count); /* * Allocate the tower reference structure to the first tower. * The number of floors is equal to the number of RPC (upper) floors * plus the number of network (lower) floors. */ rpc__tower_ref_alloc (lower_floors->tower_octet_string, RPC_C_NUM_RPC_FLOORS + lower_flr_count, RPC_C_NUM_RPC_FLOORS+1, &((*tower_vector)->tower[0]), status); if (*status != rpc_s_ok) { goto CLEANUP; } /* * Get the interface identifier and create tower floor 1. */ rpc_if_inq_id ((rpc_if_handle_t) if_spec, &if_id, status); if (*status != rpc_s_ok) { goto CLEANUP; } rpc__tower_flr_from_if_id (&if_id, &tower_floor, status); if (*status != rpc_s_ok) { goto CLEANUP; } /* * Add floor 1 to the tower. */ rpc__tower_ref_add_floor (1, tower_floor, (*tower_vector)->tower[0], status); if (*status != rpc_s_ok) { goto CLEANUP; } /* * Create tower floor 2 from the transfer syntax from the ifspec. */ if_syntax_id = if_spec->syntax_vector.syntax_id; rpc__tower_flr_from_drep (if_syntax_id, &tower_floor, status); if (*status != rpc_s_ok) { goto CLEANUP; } /* * Add floor 2 to the tower. */ rpc__tower_ref_add_floor (2, tower_floor, (*tower_vector)->tower[0], status); if (*status != rpc_s_ok) { goto CLEANUP; } /* * Create tower floor 3 from the RPC protocol id. */ rpc__tower_flr_from_rpc_prot_id (binding_rep->rpc_addr->rpc_protseq_id, binding_rep->protocol_version, &tower_floor, status); if (*status != rpc_s_ok) { goto CLEANUP; } /* * Add floor 3 to the tower. */ rpc__tower_ref_add_floor (3, tower_floor, (*tower_vector)->tower[0], status); if (*status != rpc_s_ok) { goto CLEANUP; } /* * Increment the number of towers in the vector. */ (*tower_vector)->count++; /* * Create the towers for the remaining transfer syntaxes * in the interface specification. */ if_syntax_id++; for (i=1; i < if_spec->syntax_vector.count; i++, if_syntax_id++, (*tower_vector)->count++) { /* * Copy the initial tower created. */ rpc__tower_ref_copy ((*tower_vector)->tower[0], &tower_copy, status); if (*status != rpc_s_ok) { goto CLEANUP; } /* * Create floor 2 for this tower from the next transfer syntax. */ rpc__tower_flr_from_drep (if_syntax_id, &tower_floor, status); if (*status != rpc_s_ok) { goto CLEANUP; } /* * Add floor 2 to the tower. */ rpc__tower_ref_add_floor (2, tower_floor, tower_copy, status); if (*status != rpc_s_ok) { goto CLEANUP; } (*tower_vector)->tower[i] = tower_copy; } CLEANUP: /* * If status is anything other than successful, * free the tower vector. */ if (*status != rpc_s_ok) { rpc__tower_ref_vec_free (tower_vector, &temp_status); } return; }