INTERNAL rpc_dg_client_rep_p_t find_client ( dce_uuid_p_t cas_uuid ) { rpc_dg_client_rep_p_t client; unsigned16 probe; unsigned32 st; probe = CLIENT_HASH_PROBE(cas_uuid, &st); client = client_table[probe]; while (client != NULL) { if (dce_uuid_equal(cas_uuid, &client->cas_uuid, &st)) return(client); client = client->next; } return(NULL); }
void rpc_ss_update_callee_context ( rpc_ss_context_t callee_context, /* The user's local form of the context */ dce_uuid_t *p_uuid, /* Pointer to the equivalent UUID */ error_status_t *result /* Function result */ ) { callee_context_entry_t *this_link; #ifdef PERFMON RPC_SS_UPDATE_CALLEE_CONTEXT_N; #endif RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); DPRINT(("Seized context tables\n")); this_link = &context_table[dce_uuid_hash(p_uuid,result) % CALLEE_CONTEXT_TABLE_SIZE]; while ( ! dce_uuid_equal(p_uuid,&this_link->uuid,result) ) { this_link = this_link->next_context; if (this_link == NULL) { RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); DCETHREAD_RAISE( rpc_x_ss_context_mismatch); } } this_link->user_context = callee_context; RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); *result = error_status_ok; #ifdef PERFMON RPC_SS_UPDATE_CALLEE_CONTEXT_X; #endif }
/* * R P C _ _ S E R V E R _ F W D _ R E S O L V E _ D E A L Y E D * * Remove specified packet from the list of delayed packets * and do what we are told with it */ PRIVATE void rpc__server_fwd_resolve_delayed( dce_uuid_p_t actuuid, rpc_addr_p_t fwd_addr, rpc_fwd_action_t *fwd_action, unsigned32 *status) { rpc_dg_sock_pool_elt_p_t sp; rpc_dg_recvq_elt_p_t rqe = (rpc_dg_recvq_elt_p_t)-1; rpc_dg_pkt_hdr_p_t hdrp; pkt_list_element_t *ep, *last_ep = NULL; unsigned32 st; /* get the requsted packet from the list */ *status = rpc_s_not_found; RPC_MUTEX_LOCK(fwd_list_mutex); ep = delayed_pkt_head; while (ep != NULL) { hdrp = ep->rqe->hdrp; if (dce_uuid_equal(&(hdrp->actuid), actuuid, &st) && (st == rpc_s_ok)) { /* found - remove it from the list */ rqe = ep->rqe; sp = ep->sp; if (last_ep == NULL) { delayed_pkt_head = ep->next; } else { last_ep->next = ep->next; } RPC_MEM_FREE(ep, RPC_C_MEM_UTIL); *status = rpc_s_ok; break; } last_ep = ep; ep = ep->next; } RPC_MUTEX_UNLOCK(fwd_list_mutex); if (*status != rpc_s_ok) { return; } /* * Do what we're told to do with this packet. */ switch (*fwd_action) { case rpc_e_fwd_drop: RPC_DBG_PRINTF(rpc_e_dbg_general, 10, ("(rpc__server_fwd_resolve_delayed) dropping (ptype=%s) [%s]\n", rpc__dg_pkt_name(RPC_DG_HDR_INQ_PTYPE(rqe->hdrp)), rpc__dg_act_seq_string(rqe->hdrp))); break; case rpc_e_fwd_reject: fwd_reject(sp, rqe); break; case rpc_e_fwd_forward: fwd_forward(sp, rqe, fwd_addr); break; default: *status = rpc_s_not_supported; break; } rpc__dg_network_sock_release(&sp); if (rqe == (rpc_dg_recvq_elt_p_t)-1) { fprintf(stderr, "%s: bad rqe: aborting\n", __PRETTY_FUNCTION__); abort(); } rpc__dg_pkt_free_rqe(rqe, NULL); return; }
void rpc_ss_lkddest_callee_context ( dce_uuid_t *p_uuid, /* Pointer to UUID of context to be destroyed */ rpc_client_handle_t *p_close_client, /* Ptr to NULL or client to stop monitoring */ error_status_t *result /* Function result */ ) /* Returns error_status_ok unless the UUID is not in the lookup table */ { callee_context_entry_t *this_link, *next_link, *last_link; #ifdef PERFMON RPC_SS_LKDDEST_CALLEE_CONTEXT_N; #endif this_link = &context_table[dce_uuid_hash(p_uuid,(error_status_t *) result) % CALLEE_CONTEXT_TABLE_SIZE]; next_link = this_link->next_context; if ( dce_uuid_equal(p_uuid,&this_link->uuid, (error_status_t *) result) ) { /* Context to be destroyed is in home slot */ rpc_ss_take_from_callee_client(this_link,p_close_client,result); if (next_link == NULL) { /* There is no chain from the home slot */ dce_uuid_create_nil(&this_link->uuid, (error_status_t *) result); } else { /* Move the second item in the chain to the home slot */ memcpy( (char *)&this_link->uuid, (char *)&next_link->uuid, sizeof(dce_uuid_t) ); this_link->user_context = next_link->user_context; this_link->rundown = next_link->rundown; this_link->p_client_entry = next_link->p_client_entry; this_link->prev_in_client = next_link->prev_in_client; if (this_link->prev_in_client == NULL) { (this_link->p_client_entry)->first_context = this_link; } else { (this_link->prev_in_client)->next_in_client = this_link; } this_link->next_in_client = next_link->next_in_client; if (this_link->next_in_client == NULL) { (this_link->p_client_entry)->last_context = this_link; } else { (this_link->next_in_client)->prev_in_client = this_link; } this_link->next_context = next_link->next_context; /* And release the memory it was in */ free((char_p_t)next_link); } #ifdef PERFMON RPC_SS_LKDDEST_CALLEE_CONTEXT_X; #endif return; } else /* Context is further down chain */ { while (next_link != NULL) { last_link = this_link; this_link = next_link; next_link = this_link->next_context; if ( dce_uuid_equal(p_uuid,&this_link->uuid,(error_status_t *)result) ) { rpc_ss_take_from_callee_client(this_link,p_close_client,result); /* Relink chain to omit found entry */ last_link->next_context = next_link; /* And free the memory it occupied */ free((char_p_t)this_link); #ifdef PERFMON RPC_SS_LKDDEST_CALLEE_CONTEXT_X; #endif return; } } RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); DCETHREAD_RAISE( rpc_x_ss_context_mismatch); } }
void rpc_ss_ee_ctx_from_wire ( ndr_context_handle *p_wire_context, rpc_ss_context_t *p_context, /* The application context */ volatile error_status_t *p_st ) { dce_uuid_t *p_uuid; /* Pointer to the UUID that has come off the wire */ callee_context_entry_t *this_link; #ifdef PERFMON RPC_SS_EE_CTX_FROM_WIRE_N; #endif p_uuid = &p_wire_context->context_handle_uuid; #ifdef DEBUGCTX debug_context_lookup(p_uuid); debug_context_table(); #endif *p_st = error_status_ok; if ( dce_uuid_is_nil(p_uuid, (error_status_t *)p_st) ) { *p_context = NULL; #ifdef PERFMON RPC_SS_EE_CTX_FROM_WIRE_X; #endif return; } RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); DPRINT(("Seized context tables\n")); this_link = &context_table[dce_uuid_hash(p_uuid, (error_status_t *)p_st) % CALLEE_CONTEXT_TABLE_SIZE]; while ( ! dce_uuid_equal(p_uuid,&this_link->uuid, (error_status_t *)p_st) ) { this_link = this_link->next_context; if (this_link == NULL) { RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); #ifdef PERFMON RPC_SS_EE_CTX_FROM_WIRE_X; #endif DCETHREAD_RAISE( rpc_x_ss_context_mismatch ); return; } } *p_context = this_link->user_context; RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); #ifdef PERFMON RPC_SS_EE_CTX_FROM_WIRE_X; #endif return; }
PRIVATE boolean rpc__tower_ref_is_compatible ( rpc_if_rep_p_t if_spec, rpc_tower_ref_p_t tower_ref, unsigned32 *status ) { 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 = dce_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); }
PRIVATE void rpc__tower_ref_inq_protseq_id ( rpc_tower_ref_p_t tower_ref, rpc_protseq_id_t *protseq_id, unsigned32 *status ) { 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 dce_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) && (dce_uuid_equal (&(master_prot_ids[k].uuid), &(tower_prot_ids[j].uuid), status))) { master_prot_ids[k].prefix = 0; break; } /* * Check status from dce_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; }