Пример #1
0
void rpc_ss_rundown_client
(
    /* [in] */ rpc_client_handle_t failed_client
)
{
    error_status_t result;
    callee_client_entry_t *this_client;
    callee_context_entry_t *this_context;
    rpc_client_handle_t close_client = NULL;
                                       /* NULL or client to stop monitoring */
    /* FIXME: is the volatility set correctly here? */
    rpc_ss_rundown_list_elt * volatile rundown_list;
    rpc_ss_rundown_list_elt * volatile rundown_elt;
	 
    rundown_list = NULL;

#ifdef PERFMON
    RPC_SS_RUNDOWN_CLIENT_N;
#endif

    RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex);
    DPRINT(("Seized context tables\n"));
    for( this_client = &client_table[HASH_CLIENT_ID(failed_client)];
         (this_client != NULL) && (close_client == NULL);
         this_client = this_client->next_h_client )
    {
        if (this_client->client == failed_client)
        {
            while (this_client->ref_count != 0)
            {
                this_client->rundown_pending = idl_true;
                RPC_SS_THREADS_CONDITION_WAIT(&this_client->cond_var,
                                              &rpc_ss_context_table_mutex);
                                        /* Mutex has been released */
                RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex);
            }
            if (this_client->count == 0)
            {
                /* The manager closed the contexts while a rundown was
                        pending */
                rpc_ss_ctx_remove_client_entry(this_client);
                RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex);
                DPRINT(("Released context tables\n"));
#ifdef PERFMON
                RPC_SS_RUNDOWN_CLIENT_X;
#endif
                return;
            }
            /* Need to clear the rundown pending flag so that the client
                entry can be deleted */
            this_client->rundown_pending = idl_false;
            while (close_client == NULL)
            {
                /* Loop until all contexts for this client have been removed
                    from the context table. Note that each iteration brings
                    a different context to first_context position */
                this_context = this_client->first_context;
                rundown_elt = (rpc_ss_rundown_list_elt *)
                                malloc(sizeof(rpc_ss_rundown_list_elt));
                if (rundown_elt == NULL)
                {
                    RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex);
                    DPRINT(("Released context tables\n"));
		    /*
		     * rpc_m_ctxrundown_nomem
		     * "Out of memory while trying to run down contexts of client %x"
		     */
                    RPC_DCE_SVC_PRINTF ((
		        DCE_SVC(RPC__SVC_HANDLE, "%x"),
		        rpc_svc_libidl,
		        svc_c_sev_error,
		        rpc_m_ctxrundown_nomem,
		        this_client ));
                    return;
                }
                rundown_elt->rundown = this_context->rundown;
                rundown_elt->user_context = this_context->user_context;
                rundown_elt->next = rundown_list;
                rundown_list = rundown_elt;
                rpc_ss_lkddest_callee_context
                                    (&this_context->uuid,&close_client,&result);
            }
        }
    }
    RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex);
    DPRINT(("Released context tables\n"));
    while (rundown_list != NULL)
    {
        if (rundown_list->rundown != NULL)
        {
            DCETHREAD_TRY
            (*(rundown_list->rundown))(rundown_list->user_context);
            DCETHREAD_CATCH_ALL(caught)
		/*
		 * rpc_m_ctxrundown_exc
		 * "Exception in routine at %x, running down context %x of client %x"
		 */
                RPC_DCE_SVC_PRINTF ((
		    DCE_SVC(RPC__SVC_HANDLE, "%x%x%x"),
		    rpc_svc_libidl,
		    svc_c_sev_error,
		    rpc_m_ctxrundown_exc,
                    rundown_list->rundown,
		    rundown_list->user_context,
		    this_client ));
            DCETHREAD_ENDTRY
        }
        rundown_elt = rundown_list;
        rundown_list = rundown_list->next;
        free(rundown_elt);
    }
Пример #2
0
PRIVATE void rpc__cn_call_executor 
(pointer_t arg, boolean32 call_was_queued ATTRIBUTE_UNUSED) 
{
    rpc_binding_rep_t           *binding_r;
    rpc_cn_call_rep_t           *call_r;
    rpc_iovector_t              iovector;
    dce_uuid_t                      type_uuid;
    rpc_mgr_epv_t               manager_epv;
    rpc_v2_server_stub_epv_t    server_stub_epv;
    rpc_if_rep_p_t              if_spec_rep;
    unsigned32                  flags;
    unsigned32                  max_calls;
    unsigned32                  max_rpc_size;
    rpc_if_callback_fn_t        if_callback;
    unsigned32                  status;

    RPC_LOG_CN_CTHD_NTR;

    RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL,
                   ("CN: call_rep->%x call executor running ... %s queued\n", arg, (call_was_queued ? "WAS" : "WAS NOT")));

    /*
     * The arg passed in is really a call rep.
     */
    call_r = (rpc_cn_call_rep_t *) arg;

    /*
     * Release the call rep lock which was acquired for us in the
     * common code.
     */
    RPC_CALL_UNLOCK ((rpc_call_rep_t *) call_r);

    /*
     * If there is an object uuid, see if there's a type uuid
     * associated with it.
     */
    rpc_object_inq_type (&call_r->binding_rep->obj, &type_uuid, &status);
    if ((status != rpc_s_object_not_found) && (status != rpc_s_ok))
    {
        RPC_CALL_LOCK ((rpc_call_rep_t *) call_r);
        rpc__cthread_cancel_caf ((rpc_call_rep_t *) call_r);
        RPC_CALL_UNLOCK ((rpc_call_rep_t *) call_r);
        RPC_CN_LOCK ();
        rpc__cn_call_reject ((rpc_call_rep_p_t) call_r, status);
        RPC_CN_UNLOCK ();
        goto CLEANUP;
    }
    
    /*
     * Get the if rep and the server stub and manager EPV.
     */
    rpc__if_lookup2 (call_r->u.server.if_id,
                     call_r->u.server.if_vers,
                     &type_uuid, 
                     &call_r->u.server.ihint, 
                     &if_spec_rep,
                     &server_stub_epv, 
                     &manager_epv, 
                     &flags, 
                     &max_calls, 
                     &max_rpc_size, 
                     &if_callback, 
                     &status);
    if (status != rpc_s_ok)
    {
        RPC_CALL_LOCK ((rpc_call_rep_t *) call_r);
        rpc__cthread_cancel_caf ((rpc_call_rep_t *) call_r);
        RPC_CALL_UNLOCK ((rpc_call_rep_t *) call_r);
        RPC_CN_LOCK ();
        rpc__cn_call_reject ((rpc_call_rep_p_t) call_r, status);
        RPC_CN_UNLOCK ();
        goto CLEANUP;
    }
    
    /*
     * If the operation number is out of range, indicate a fault to
     * the protocol service, otherwise process the incoming packet(s).
     */
    if (call_r->opnum >= if_spec_rep->opcnt)
    {
        RPC_CALL_LOCK ((rpc_call_rep_t *) call_r);
        rpc__cthread_cancel_caf ((rpc_call_rep_t *) call_r);
        RPC_CALL_UNLOCK ((rpc_call_rep_t *) call_r);
        RPC_CN_LOCK ();
        rpc__cn_call_reject ((rpc_call_rep_p_t) call_r, rpc_s_op_rng_error);
        RPC_CN_UNLOCK ();
        goto CLEANUP;
    }

    /*
     * Receive the first packet.
     */
    rpc__cn_call_receive ((rpc_call_rep_t *) call_r,
                          &iovector.elt[0], 
                          &status);
    if (status != rpc_s_ok)
    {
        RPC_CALL_LOCK ((rpc_call_rep_t *) call_r);
        rpc__cthread_cancel_caf ((rpc_call_rep_t *) call_r);
        RPC_CALL_UNLOCK ((rpc_call_rep_t *) call_r);
        RPC_CN_LOCK ();
        rpc__cn_call_reject ((rpc_call_rep_p_t) call_r, rpc_s_op_rng_error);
        RPC_CN_UNLOCK ();
        goto CLEANUP;
    }
    
    /*
     * Mark the call as having executed.
     */
    call_r->call_executed = true;
    
    /*
     * Enable posting of cancels to this call executor thread.
     * This will also post any queued cancels.
     */
    RPC_DBG_PRINTF (rpc_e_dbg_cancel, RPC_C_CN_DBG_CANCEL,
                   ("(rpc__cn_call_executor) call_rep->%x enabling posting of cancels and posting any queued cancels\n", call_r));
    RPC_CALL_LOCK ((rpc_call_rep_t *) call_r);
    rpc__cthread_cancel_enable_post ((rpc_call_rep_p_t) call_r);
    RPC_CALL_UNLOCK ((rpc_call_rep_t *) call_r);
   
    /*
     * Dispatch appropriately depending on the stub version.
     */
    switch (if_spec_rep->stub_rtl_if_vers)
    {
        /*
         * If this is an old v0 or v1 stub runtime interface
         * then do the dirty work out of line.
         */
        case 0:
        case 1:
	/*
	 * rpc_m_pre_v2_ifspec
	 * "(%s) Pre-v2 interface spec"
	 */
	RPC_DCE_SVC_PRINTF ((
	    DCE_SVC(RPC__SVC_HANDLE, "%s"),
	    rpc_svc_server_call,
	    svc_c_sev_fatal | svc_c_action_abort,
	    rpc_m_pre_v2_ifspec,
	    "rpc__cn_call_executor" ));
	break;

        /*
         * This is the v2 (new) stub runtime interface.
         */
        case 2:
        
        RPC_LOG_SERVER_STUB_PRE;
        ((*server_stub_epv[call_r->opnum])) 
        ((handle_t) call_r->binding_rep,
         (rpc_call_handle_t) call_r,
         &iovector.elt[0],
         &(RPC_CN_ASSOC_NDR_FORMAT (call_r->assoc)),
         &call_r->transfer_syntax,
         manager_epv, 
         &status);
        RPC_LOG_SERVER_STUB_POST;
        break;
        
        /*
         * Unknown version
         */
        default:
	/*
	 * rpc_m_unk_ifspec
	 * "(%s) Unknown interface spec version"
	 */
	RPC_DCE_SVC_PRINTF ((
	    DCE_SVC(RPC__SVC_HANDLE, "%s"),
	    rpc_svc_server_call,
	    svc_c_sev_fatal | svc_c_action_abort,
	    rpc_m_pre_v2_ifspec,
	    "rpc__cn_call_executor" ));
	break;
    }

    /*
     * Check for an error while in the server stub but before the
     * manager routine was entered.
     */
    if (status != rpc_s_ok)
    {
        RPC_CALL_LOCK ((rpc_call_rep_t *) call_r);
        rpc__cthread_cancel_caf ((rpc_call_rep_t *) call_r);
        RPC_CALL_UNLOCK ((rpc_call_rep_t *) call_r);
        RPC_CN_LOCK ();
        rpc__cn_call_reject ((rpc_call_rep_p_t) call_r, status);
        RPC_CN_UNLOCK ();
        goto CLEANUP;
    }

    /*
     * If the stub returned successfully, end the call and free the binding handle.
     */
    binding_r = (rpc_binding_rep_t *) call_r->binding_rep;
    RPC_CALL_LOCK ((rpc_call_rep_t *) call_r);
    rpc__cthread_cancel_caf ((rpc_call_rep_t *) call_r);
    RPC_CALL_UNLOCK ((rpc_call_rep_t *) call_r);

CLEANUP:
    binding_r = (rpc_binding_rep_t *) call_r->binding_rep;
    rpc__cn_call_end ((rpc_call_rep_p_t *) &call_r, &status);
    RPC_LOCK (0);
    RPC_BINDING_RELEASE (&binding_r,
                         &status);
    RPC_UNLOCK (0);
    RPC_LOG_CN_CTHD_XIT;
}
Пример #3
0
PRIVATE void rpc__cn_unpack_hdr
(
  rpc_cn_packet_p_t pkt_p
)
{
    rpc_cn_auth_tlr_p_t authp;           /* ptr to pkt authentication data */
    rpc_cn_pres_cont_list_p_t pconp;     /* ptr to pkt presentation context lists */
    rpc_cn_pres_result_list_p_t presp;   /* ptr to pkt presentation result lists */
    rpc_cn_port_any_p_t secadrp;         /* ptr to pkt secondary address data */
    rpc_cn_versions_supported_p_t versp; /* ptr to pkt versions supported data */
    unsigned8 *drepp;                    /* ptr to pkt drep[] data */
    boolean swap;                        /* boolean says we swap bytes/words */
    boolean authenticate;                /* boolean says authentication data is valid */
    boolean has_uuid;		         /* boolean says an OBJECT uuid is present */
    unsigned32 st;                       /* status variable */

    /*
     * Get the DREP and see if we need to do byte/word swapping.
     */
    drepp = RPC_CN_PKT_DREP (pkt_p);
    swap = (NDR_DREP_INT_REP (drepp) != NDR_LOCAL_INT_REP);

    /*
     * RPC_CN_COMMON_HDR_T
     *
     * Unpack the common part of the packet header.
     */
    if (swap)
    {
        SWAB_INPLACE_16 (RPC_CN_PKT_FRAG_LEN (pkt_p));
        SWAB_INPLACE_16 (RPC_CN_PKT_AUTH_LEN (pkt_p));
        SWAB_INPLACE_32 (RPC_CN_PKT_CALL_ID (pkt_p));
    }

    /*
     * See if the authentication data is valid.
     */
    authenticate = RPC_CN_PKT_AUTH_LEN(pkt_p) != 0;
    authp = NULL;

    /*
     * Check for the presence of an OBJECT uuid.
     */
    has_uuid = (RPC_CN_PKT_FLAGS (pkt_p) & RPC_C_CN_FLAGS_OBJECT_UUID) != 0;

    /*
     * Unpack the packet-type specific part of the packet. We also find the
     * start of the authentication data if there is any.
     */
    switch (RPC_CN_PKT_PTYPE (pkt_p))
    {
            /*
             * RPC_CN_BIND_HDR_T
             */
        case RPC_C_CN_PKT_BIND:
        case RPC_C_CN_PKT_ALTER_CONTEXT:
            if (swap)
            {
                SWAB_INPLACE_16 (RPC_CN_PKT_MAX_XMIT_FRAG (pkt_p));
                SWAB_INPLACE_16 (RPC_CN_PKT_MAX_RECV_FRAG (pkt_p));
                SWAB_INPLACE_32 (RPC_CN_PKT_ASSOC_GROUP_ID (pkt_p));
            }
            pconp = (rpc_cn_pres_cont_list_p_t)((unsigned8 *)(&RPC_CN_PKT_ASSOC_GROUP_ID (pkt_p)) + 4);
            authp = unpack_pres_context_list (pconp, swap);
            break;

            /*
             * RPC_CN_BIND_ACK_HDR_T
             */
        case RPC_C_CN_PKT_BIND_ACK:
        case RPC_C_CN_PKT_ALTER_CONTEXT_RESP:
            if (swap)
            {
                SWAB_INPLACE_16 (RPC_CN_PKT_MAX_XMIT_FRAG (pkt_p));
                SWAB_INPLACE_16 (RPC_CN_PKT_MAX_RECV_FRAG (pkt_p));
                SWAB_INPLACE_32 (RPC_CN_PKT_ASSOC_GROUP_ID (pkt_p));
            }
            secadrp = (rpc_cn_port_any_t *)
                ((unsigned8 *)(pkt_p) + RPC_CN_PKT_SIZEOF_BIND_ACK_HDR);
            presp = unpack_port_any (secadrp, drepp);
            force_alignment (4, (unsigned8 **)&presp);
            authp = unpack_pres_result_list (presp, swap);
            break;

            /*
             * RPC_CN_BIND_NACK_HDR_T
             */
        case RPC_C_CN_PKT_BIND_NAK:
            if (swap)
            {
                SWAB_INPLACE_16 (RPC_CN_PKT_PROV_REJ_REASON (pkt_p));
            }
	    versp = &RPC_CN_PKT_VERSIONS (pkt_p);
            authp = unpack_versions_supported (versp);
            break;

            /*
             * RPC_CN_REQUEST_HDR_T
             */
        case RPC_C_CN_PKT_REQUEST:
            if (swap)
            {
                SWAB_INPLACE_32 (RPC_CN_PKT_ALLOC_HINT (pkt_p));
                SWAB_INPLACE_16 (RPC_CN_PKT_PRES_CONT_ID (pkt_p));
                SWAB_INPLACE_16 (RPC_CN_PKT_OPNUM (pkt_p));
		if (has_uuid)
		{
                    SWAB_INPLACE_UUID (RPC_CN_PKT_OBJECT (pkt_p));
                }
            }
            authp = end_of_stub_data (pkt_p);
            break;

            /*
             * RPC_CN_RESPONSE_HDR_T
             */
        case RPC_C_CN_PKT_RESPONSE:
            if (swap)
            {
                SWAB_INPLACE_32 (RPC_CN_PKT_ALLOC_HINT (pkt_p));
                SWAB_INPLACE_16 (RPC_CN_PKT_PRES_CONT_ID (pkt_p));
            }
            authp = end_of_stub_data (pkt_p);
            break;

	    /*
	     * RPC_CN_FAULT_HDR_T
	     */
        case RPC_C_CN_PKT_FAULT:
            if (swap)
            {
		SWAB_INPLACE_32 (RPC_CN_PKT_ALLOC_HINT (pkt_p));
                SWAB_INPLACE_16 (RPC_CN_PKT_PRES_CONT_ID (pkt_p));
		SWAB_INPLACE_32 (RPC_CN_PKT_STATUS (pkt_p));
            }
            authp = end_of_stub_data (pkt_p);
            break;

            /*
             * RPC_CN_AUTH3_HDR_T
             */
        case RPC_C_CN_PKT_SHUTDOWN:
        case RPC_C_CN_PKT_AUTH3:
        case RPC_C_CN_PKT_REMOTE_ALERT:
        case RPC_C_CN_PKT_ORPHANED:
            break;

        default:
            /* "(%s) Illegal or unknown packet type: %x\n" */
	    RPC_DCE_SVC_PRINTF ((
	        DCE_SVC(RPC__SVC_HANDLE, "%s%x"),
	        rpc_svc_cn_pkt,
	        svc_c_sev_warning,
	        rpc_m_bad_pkt_type,
	        "rpc__cn_unpack_hdr",
	        RPC_CN_PKT_PTYPE(pkt_p) ));
            return;
    }

    /*
     * Unpack the authentication part of the packet if it exists.
     */
    if (authenticate && swap)
    {
        switch (RPC_CN_PKT_PTYPE (pkt_p))
        {
	    case RPC_C_CN_PKT_BIND:
	    case RPC_C_CN_PKT_ALTER_CONTEXT:
	    case RPC_C_CN_PKT_BIND_ACK:
	    case RPC_C_CN_PKT_ALTER_CONTEXT_RESP:
	    case RPC_C_CN_PKT_BIND_NAK:
	    case RPC_C_CN_PKT_AUTH3:
            {
#ifdef DEBUG
		char *p;
#endif
                rpc_authn_protocol_id_t authn_protocol;

		authp = RPC_CN_PKT_AUTH_TLR (pkt_p, RPC_CN_PKT_FRAG_LEN (pkt_p));
#ifdef DEBUG
		p = (char *)authp;
		force_alignment(4, (unsigned8 **)&authp);
		if (p != (char *)authp) {
		    /*
		     * rpc_m_unalign_authtrl
		     * "(%s) Unaligned RPC_CN_PKT_AUTH_TRL"
		     */
		    RPC_DCE_SVC_PRINTF ((
			DCE_SVC(RPC__SVC_HANDLE, "%s"),
			rpc_svc_cn_pkt,
			svc_c_sev_fatal | svc_c_action_abort,
			rpc_m_unalign_authtrl,
			"rpc__cn_unpack_hdr" ));
                }
#endif

                SWAB_INPLACE_32(authp->key_id);

                authn_protocol = RPC_CN_AUTH_CVT_ID_WIRE_TO_API (authp->auth_type, &st);
                if (st == rpc_s_ok)
                {
                    RPC_CN_AUTH_TLR_UNPACK (authn_protocol,
				            pkt_p, RPC_CN_PKT_AUTH_LEN (pkt_p), drepp);
                }
                break;
	    }

            default:
		/*
	         * We do not need the auth trailer of the other packet
                 * types since they are thrown away after recv_check.
                 * So don't bother to unpack them in these cases.
	         */
            break;
        }
    }
}