Beispiel #1
0
void dce_rpc_server_main ()
{
    unsigned32 status;
    int ret;

    strcpy(pszProtocolSequence,"ncacn_ip_tcp");
    pszEndpoint = NULL;
    cMaxCalls = 1;
    pbvBindings = NULL;

    pthread_mutex_init(&mutex,pthread_mutexattr_default);
    /* No RPCs now! */
    pthread_mutex_lock(&mutex);

    /* Initialize DCE RPC */
    rpc_server_use_protseq(pszProtocolSequence,cMaxCalls,&status);
    CHECK_DCE_ERROR(status,ABORT);
    rpc_server_inq_bindings(&pbvBindings,&status);
    CHECK_DCE_ERROR(status,ABORT);
    rpc_ep_register(xgobi_goes_dce_v1_0_s_ifspec,pbvBindings,0,0,&status);
    CHECK_DCE_ERROR(status,ABORT);
    rpc_server_register_if(xgobi_goes_dce_v1_0_s_ifspec,0,0,&status);
    CHECK_DCE_ERROR(status,ABORT);

/* p-Thread to rpc_server_listen */
    ret = pthread_create(&t_handle,pthread_attr_default,
            (void *(*)(void *)) dce_rpc_server_listen,NULL);
}
/* Common routine for embedded RPC servers */
bool rpc_setup_embedded(struct tevent_context *ev_ctx,
			struct messaging_context *msg_ctx,
			const struct ndr_interface_table *t,
			const char *pipe_name)
{
	struct dcerpc_binding_vector *v;
	enum rpc_service_mode_e epm_mode = rpc_epmapper_mode();
	NTSTATUS status;

	/* Registration of ncacn_np services is problematic.  The
	 * ev_ctx passed in here is passed down to all children of the
	 * smbd process, and if the end point mapper ever goes away,
	 * they will all attempt to re-register.  But we want to test
	 * the code for now, so it is enabled in on environment in
	 * make test */
	if (epm_mode != RPC_SERVICE_MODE_DISABLED && 
	    (lp_parm_bool(-1, "rpc_server", "register_embedded_np", false))) {
		status = dcerpc_binding_vector_new(talloc_tos(), &v);
		if (!NT_STATUS_IS_OK(status)) {
			return false;
		}

		status = dcerpc_binding_vector_add_np_default(t, v);
		if (!NT_STATUS_IS_OK(status)) {
			return false;
		}

		status = rpc_ep_register(ev_ctx,
					 msg_ctx,
					 t,
					 v);
		if (!NT_STATUS_IS_OK(status)) {
			return false;
		}
	}

	return true;
}
Beispiel #3
0
DWORD
VmDnsRpcEpRegister(
    rpc_binding_vector_p_t pServerBinding,
    rpc_if_handle_t        pInterfaceSpec,
    PCSTR                  pszAnnotation
    )
{
    DWORD dwError = 0;
#if 1
    /* Do not register with dcerpc; all services use fixed endpoints */
    return dwError;
#else
    DCETHREAD_TRY
    {
       rpc_ep_register(
                pInterfaceSpec,
                pServerBinding,
                NULL,
                (idl_char*)pszAnnotation,
                (unsigned32*)&dwError);
    }
    DCETHREAD_CATCH_ALL(THIS_CATCH)
    {
        if (dwError == rpc_s_ok )
        {
            dwError = dcethread_exc_getstatus(THIS_CATCH);
            if (!dwError)
            {
               dwError = RPC_S_INTERNAL_ERROR;
            }
        }
    }
    DCETHREAD_ENDTRY;

    return dwError;
#endif
}
int main ( int argc, char *argv[] )
{
   rpc_binding_vector_t *bv_p;
   unsigned32 status;

   /* Register interface/epv associations with RPC runtime.                   */
   printf("Registering server interface with RPC runtime...\n");
   rpc_server_register_if ( mathb_v1_0_s_ifspec, NULL, NULL, &status );
   ERRCHK ( status );

   /* Inform RPC runtime to use a supported protocol sequences.               */
   rpc_server_use_protseq ( "ncadg_ip_udp", MAX_CONC_CALLS_PROTSEQ, &status );
   ERRCHK ( status );

   /* Get the binding handle vector from RPC runtime.                         */
   rpc_server_inq_bindings ( &bv_p, &status );
   ERRCHK ( status );

   /* Register binding information with endpoint map.                         */
   printf("Registering server endpoints with endpoint mapper (RPCD)...\n");
   rpc_ep_register ( mathb_v1_0_s_ifspec, bv_p, NULL,
                     ( unsigned_char_t * )"Basic math server, version 1.0",
                     &status );
   ERRCHK ( status );

   /* Export binding information to the namespace.                            */
   printf("Exporting server bindings into CDS namespace...\n");
   rpc_ns_binding_export ( rpc_c_ns_syntax_dce, ENTRY_NAME,
                           mathb_v1_0_s_ifspec, bv_p, NULL, &status );
   ERRCHK ( status );

   /* Listen for service requests.                                            */
   printf ( "Server %s listening...\n", ENTRY_NAME );
   rpc_server_listen ( MAX_CONC_CALLS_TOTAL, &status );
   ERRCHK ( status );
}
int main( int argc, char *argv[] )
{
   unsigned32 st;
   rpc_binding_vector_t  *bvec;

#ifndef _WINDOWS
   sigset_t              sigset;
   pthread_t             this_thread = pthread_self();
#endif

#ifdef IBMOS2
   pthread_inst_exception_handler();
#endif

   /* Register interface/epv associations with rpc runtime.                   */
   printf("Registering server interface with RPC runtime...\n");
   rpc_server_register_if( MyError_v1_0_s_ifspec, NULL, NULL, &st );
   ERRORCK( "rpc_server_register_if", st );

   rpc_server_use_protseq ( "ncadg_ip_udp", MAX_CALL_REQUESTS, &st );
   ERRORCK( "rpc_server_use_protseq", st );

   rpc_server_inq_bindings( &bvec, &st );
   ERRORCK( "rpc_server_inq_binding", st );

   /* Register binding information with endpoint map                          */
   printf("Registering server endpoints with endpoint mapper (RPCD)...\n");
   rpc_ep_register( MyError_v1_0_s_ifspec, bvec, NULL,
       (unsigned_char_t *)"MyError3, version 1.0", &st );
   ERRORCK( "rpc_ep_register", st );

   /* Export binding info to the namespace.                                   */
   printf("Exporting server bindings into CDS namespace...\n");
   rpc_ns_binding_export( rpc_c_ns_syntax_dce, ENTRY_NAME,
         MyError_v1_0_s_ifspec, bvec, NULL, &st );
   ERRORCK( "rpc_ns_binding_export", st );

#ifndef _WINDOWS
   sigemptyset ( &sigset );
   sigaddset ( &sigset, SIGINT );
   sigaddset ( &sigset, SIGTERM);
   pthread_signal_to_cancel_np ( &sigset, &this_thread );
#endif

   TRY
      /* Listen for service requests.                                         */
      printf( "Server %s listening...\n", ENTRY_NAME );
      rpc_server_listen( MAX_CALL_REQUESTS, &st );
   FINALLY
      printf("Unexporting server bindings from CDS namespace...\n");
      rpc_ns_binding_unexport( rpc_c_ns_syntax_dce, ENTRY_NAME,
            MyError_v1_0_s_ifspec, NULL, &st );
      ERRORCK( "rpc_ns_binding_unexport", st );

      printf("Unregistering server interface with RPC runtime...\n");
      rpc_server_unregister_if( MyError_v1_0_s_ifspec, NULL, &st );
      ERRORCK( "rpc_server_unregister_if", st );

      printf("Unregistering server endpoints with endpoint mapper (RPCD)...\n");
      rpc_ep_unregister( MyError_v1_0_s_ifspec, bvec, NULL, &st );
      ERRORCK( "rpc_ep_unregister", st );

#ifdef IBMOS2
      pthread_dinst_exception_handler();
#endif
      exit( 0 );
   ENDTRY;
}
Beispiel #6
0
DWORD
WinRegRegisterForRPC(
    PSTR pszServiceName,
    rpc_binding_vector_p_t* ppServerBinding
    )
{
    volatile DWORD dwError = 0;
    volatile DWORD dwRpcStatus = 0;
    rpc_binding_vector_p_t pServerBinding = NULL;
    BOOLEAN bRegistered = FALSE;
    BOOLEAN bBound = FALSE;
    BOOLEAN bEPRegistered = FALSE;
    static ENDPOINT endpoints[] =
    {
        {"ncacn_ip_tcp", NULL},
        {"ncacn_np"    , "\\\\pipe\\\\winreg"},
        {NULL          , NULL}
    };

    DCETHREAD_TRY
    {
        rpc_server_register_if(winreg_v1_0_s_ifspec,
                               NULL,
                               NULL,
                               (unsigned32*)&dwRpcStatus);
    }
    DCETHREAD_CATCH_ALL(THIS_CATCH)
    {
        if (dwRpcStatus == RPC_S_OK)
        {
            dwError = dcethread_exc_getstatus(THIS_CATCH);
            if (!dwError)
            {
                dwError = SRVSVC_ERROR_RPC_EXCEPTION_UPON_REGISTER;
            }
        }
    }
    DCETHREAD_ENDTRY;

    BAIL_ON_DCE_ERROR(dwError, dwRpcStatus);
    BAIL_ON_SRVSVC_ERROR(dwError);

    bRegistered = TRUE;
    SRVSVC_LOG_INFO("RPC Service registered successfully.");

    DCETHREAD_TRY
    {
        dwError = bind_server(&pServerBinding,
                              winreg_v1_0_s_ifspec,
                              endpoints);
    }
    DCETHREAD_CATCH_ALL(THIS_CATCH)
    {
        if (!dwError)
        {
            dwError = dcethread_exc_getstatus(THIS_CATCH);
        }
        if (!dwError)
        {
            dwError = SRVSVC_ERROR_RPC_EXCEPTION_UPON_REGISTER;
        }
    }
    DCETHREAD_ENDTRY;

    BAIL_ON_SRVSVC_ERROR(dwError);

    bBound = TRUE;

    DCETHREAD_TRY
    {
        rpc_ep_register(winreg_v1_0_s_ifspec,
                        pServerBinding,
                        NULL,
                        (idl_char*)pszServiceName,
                        (unsigned32*)&dwRpcStatus);
    }
    DCETHREAD_CATCH_ALL(THIS_CATCH)
    {
        if (dwRpcStatus == RPC_S_OK)
        {
            dwError = dcethread_exc_getstatus(THIS_CATCH);
            if (!dwError)
            {
                dwError = SRVSVC_ERROR_RPC_EXCEPTION_UPON_REGISTER;
            }
        }
    }
    DCETHREAD_ENDTRY;

    BAIL_ON_DCE_ERROR(dwError, dwRpcStatus);
    BAIL_ON_SRVSVC_ERROR(dwError);

    bEPRegistered = TRUE;
    SRVSVC_LOG_INFO("RPC Endpoint registered successfully.");

    *ppServerBinding = pServerBinding;

cleanup:

    return dwError;

error:

    SRVSVC_LOG_ERROR("Failed to register RPC endpoint.  Error Code: [%u]\n", dwError);

    if (bEPRegistered)
    {
        DCETHREAD_TRY
        {
            DWORD tmpStatus = 0;
            rpc_ep_unregister(winreg_v1_0_s_ifspec,
                              pServerBinding,
                              NULL,
                              (unsigned32*)&tmpStatus);
        }
        DCETHREAD_CATCH_ALL(THIS_CATCH)
        DCETHREAD_ENDTRY;
    }

    if (bBound)
    {
        DCETHREAD_TRY
        {
            DWORD tmpStatus = 0;
            rpc_binding_vector_free(&pServerBinding,
                                    (unsigned32*)&tmpStatus);
        }
        DCETHREAD_CATCH_ALL(THIS_CATCH)
        DCETHREAD_ENDTRY;
    }

    if (bRegistered)
    {
        DCETHREAD_TRY
        {
            DWORD tmpStatus = 0;
            rpc_server_unregister_if(winreg_v1_0_s_ifspec,
                                     NULL,
                                     (unsigned32*)&tmpStatus);
        }
        DCETHREAD_CATCH_ALL(THIS_CATCH)
        DCETHREAD_ENDTRY;
    }

    *ppServerBinding = NULL;

    goto cleanup;
}
int main ( int argc, char *argv[] )
{
        unsigned_char_t         *server_name;
        rpc_binding_vector_t    *bind_vector_p;
        unsigned32              status;
# ifndef _WINDOWS
        sigset_t                sigset;
        pthread_t               this_thread     = pthread_self();
# endif

# ifdef IBMOS2
        pthread_inst_exception_handler();
# endif

        /* Register the authentification level which will be used */
        printf("Registering authentication level with RPC runtime...\n");
        rpc_server_register_auth_info(
                PRINCIPAL_NAME,
                rpc_c_authn_default,
                NULL,
                NULL,
                &status
        );
        ERRCHK( status );

        /* Register interface/epv associations with rpc runtime. */
        printf("Registering server interface with RPC runtime...\n");
        rpc_server_register_if ( IF_HANDLE, NULL, NULL, &status );
        ERRCHK( status );

        /* Inform rpc runtime of a protocol sequence to use. */
        switch ( (( argc > 1 ) ? *argv[1] | ' ' : 'a') ) {
        case 't':
           rpc_server_use_protseq ("ncacn_ip_tcp", MAX_CONC_CALLS_PROTSEQ, &status );
           break;
        case 'u':
           rpc_server_use_protseq ("ncadg_ip_udp", MAX_CONC_CALLS_PROTSEQ, &status );
           break;
        case 'a':
        default:
           rpc_server_use_all_protseqs ( MAX_CONC_CALLS_PROTSEQ, &status );
        }
        ERRCHK( status );

        /* Ask the runtime which binding handle will be used. */
        rpc_server_inq_bindings( &bind_vector_p, &status );
        ERRCHK( status );

        /* Register binding information with endpoint map */
        printf("Registering server endpoints with endpoint mapper (RPCD)...\n");
        rpc_ep_register(
                IF_HANDLE,
                bind_vector_p,
                NULL,
                "Message Box server, version 2.0",
                &status
        );
        ERRCHK( status );

        /* Export binding info to the namespace. */
        printf("Exporting server bindings into CDS namespace...\n");
        rpc_ns_binding_export (
                rpc_c_ns_syntax_default,
                ENTRY_NAME,
                IF_HANDLE,
                bind_vector_p,
                NULL,
                &status
        );
        ERRCHK( status );

# ifndef _WINDOWS
        /* baggage to handle ctrl-C */
        sigemptyset(&sigset);
        sigaddset(&sigset, SIGINT);
        sigaddset(&sigset, SIGTERM);
        if (pthread_signal_to_cancel_np(&sigset, &this_thread) != 0) {
                printf("pthread_signal_to_cancel_np failed\n");
                exit(1);
        }
# endif

        /* Import the mbox structure from file FNAME */
        mbox_import(FNAME);

        TRY {
                /* Listen for service requests. */
                printf( "Server %s listening...\n", ENTRY_NAME );
                rpc_server_listen ( MAX_CONC_CALLS_TOTAL, &status );
                ERRCHK( status );
        }
        FINALLY {
                /* Export the mbox structure to file FNAME */
                mbox_export(FNAME);

                /* Unexport the binding information from the namespace. */
                printf("Unexporting server bindings from CDS namespace...\n");
                rpc_ns_binding_unexport (
                        rpc_c_ns_syntax_default,
                        ENTRY_NAME,
                        IF_HANDLE,
                        NULL,
                        &status
                );
                ERRCHK( status );

                /* Unregister interface from RPC runtime */
                printf("Unregistering server interface with RPC runtime...\n");
                rpc_server_unregister_if ( IF_HANDLE, NULL, &status );
                ERRCHK( status );

                /* Unregister interface from EPV */
                printf("Unregistering server endpoints with endpoint mapper (RPCD)...\n");
                rpc_ep_unregister ( IF_HANDLE, bind_vector_p, NULL, &status );
                ERRCHK( status );

# ifdef IBMOS2
                pthread_dinst_exception_handler();
# endif
                exit ( 0 );
        }
        ENDTRY;
}
int main( int argc, char *argv[] )
{
   unsigned32 st;
   rpc_binding_vector_t  *bvec;
#ifndef _WINDOWS
   sigset_t              sigset;
   pthread_t             this_thread = pthread_self();
#endif

#ifdef IBMOS2
   pthread_inst_exception_handler();
#endif

   printf("Registering server interface with RPC runtime...\n");
   rpc_server_register_if( Database_v1_0_s_ifspec, NULL, NULL, &st );
   ERRORCK( "rpc_server_register_if", st );

   switch ( (( argc > 1 ) ? *argv[1] | ' ' : 'a') ) {
   case 't':
      rpc_server_use_protseq ("ncacn_ip_tcp", MAX_CONC_CALLS_PROTSEQ, &st );
      break;
   case 'u':
      rpc_server_use_protseq ("ncadg_ip_udp", MAX_CONC_CALLS_PROTSEQ, &st );
      break;
   case 'a':
   default:
      rpc_server_use_all_protseqs ( MAX_CONC_CALLS_PROTSEQ, &st );
   }
   ERRORCK( "rpc_server_use_all_protseqs", st );

   rpc_server_inq_bindings( &bvec, &st );
   ERRORCK( "rpc_server_inq_binding", st );

   printf("Registering server endpoints with endpoint mapper (RPCD)...\n");
   rpc_ep_register( Database_v1_0_s_ifspec, bvec, NULL,
                    ( unsigned_char_t * )"Database server, version 1.0" , &st );
   ERRORCK( "rpc_ep_register", st );

   rpc_ns_binding_export( rpc_c_ns_syntax_dce, ENTRY_NAME,
         Database_v1_0_s_ifspec, bvec, NULL, &st );
   ERRORCK( "rpc_ns_binding_export", st );

#ifndef _WINDOWS
   sigemptyset ( &sigset );
   sigaddset ( &sigset, SIGINT );
   sigaddset ( &sigset, SIGTERM );
   pthread_signal_to_cancel_np ( &sigset, &this_thread );
#endif

   TRY {
      printf ( "Server %s listening...\n", ENTRY_NAME );
      rpc_server_listen( MAX_CALL_REQUESTS, &st );
   }
   FINALLY {
      printf("Unexporting server bindings from CDS namespace...\n");
      rpc_ns_binding_unexport( rpc_c_ns_syntax_dce, ENTRY_NAME,
            Database_v1_0_s_ifspec, NULL, &st );
      ERRORCK( "rpc_ns_binding_unexport", st );

      printf("Unregistering server interface with RPC runtime...\n");
      rpc_server_unregister_if( Database_v1_0_s_ifspec, NULL, &st );
      ERRORCK( "rpc_server_unregister_if", st );

      printf("Unregistering server endpoints with endpoint mapper (RPCD)...\n");
      rpc_ep_unregister( Database_v1_0_s_ifspec, bvec, NULL, &st );
      ERRORCK( "rpc_ep_unregister", st );

#ifdef IBMOS2
      pthread_dinst_exception_handler();
#endif
      exit( 0 );
   }
   ENDTRY
}
Beispiel #9
0
DWORD
SrvSvcRegisterForRPC(
    PSTR pszServiceName,
    rpc_binding_vector_p_t* ppServerBinding
    )
{
    volatile DWORD dwError = 0;
    volatile DWORD dwRpcStatus = 0;
    rpc_binding_vector_p_t pServerBinding = NULL;
    BOOLEAN bRegistered = FALSE;
    BOOLEAN bBound = FALSE;
    BOOLEAN bEPRegistered = FALSE;
    static ENDPOINT endpoints[] =
    {
        {"ncacn_np",   "\\\\pipe\\\\srvsvc"},
        {"ncalrpc",    NULL}, // endpoint is fetched from config parameter
        {NULL,         NULL}, // placeholder for ncacn_ip_tcp (if enabled)
        {NULL,         NULL}
    };
    DWORD i = 0;
    PSTR lpcSocketPath = NULL;
    BOOLEAN registerTcpIp = FALSE;

    dwError = SrvSvcConfigGetLpcSocketPath(&lpcSocketPath);
    BAIL_ON_SRVSVC_ERROR(dwError);

    // Fill in the socket path for local procedure calls (ncalrpc)
    while (endpoints[i].protocol) {
        if (lpcSocketPath &&
            LwRtlCStringIsEqual(endpoints[i].protocol,
                                "ncalrpc",
                                TRUE))
        {
            endpoints[i].endpoint = lpcSocketPath;
        }

        i++;
    }

    dwError = SrvSvcConfigGetRegisterTcpIp(&registerTcpIp);
    BAIL_ON_SRVSVC_ERROR(dwError);

    // Append ncacn_ip_tcp endpoint if it's enabled in the configuration
    if (registerTcpIp)
    {
        endpoints[i++].protocol = "ncacn_ip_tcp";
    }

    DCETHREAD_TRY
    {
        rpc_server_register_if (srvsvc_v3_0_s_ifspec,
                                NULL,
                                NULL,
                                (unsigned32*)&dwRpcStatus);
    }
    DCETHREAD_CATCH_ALL(THIS_CATCH)
    {
        if ( dwRpcStatus == RPC_S_OK )
        {
            dwError = dcethread_exc_getstatus (THIS_CATCH);
            if(!dwError)
            {
                dwError = SRVSVC_ERROR_RPC_EXCEPTION_UPON_REGISTER;
            }
        }
    }
    DCETHREAD_ENDTRY;

    BAIL_ON_DCE_ERROR(dwError, dwRpcStatus);
    BAIL_ON_SRVSVC_ERROR(dwError);

    bRegistered = TRUE;
    SRVSVC_LOG_INFO("RPC Service registered successfully.");

    DCETHREAD_TRY
    {
        dwError = bind_server(&pServerBinding,
                              srvsvc_v3_0_s_ifspec,
                              endpoints);
    }
    DCETHREAD_CATCH_ALL(THIS_CATCH)
    {
        if(!dwError)
        {
            dwError = dcethread_exc_getstatus (THIS_CATCH);
        }
        if(!dwError)
        {
            dwError = SRVSVC_ERROR_RPC_EXCEPTION_UPON_REGISTER;
        }
    }
    DCETHREAD_ENDTRY;

    BAIL_ON_SRVSVC_ERROR(dwError);

    bBound = TRUE;

    DCETHREAD_TRY
    {
        rpc_ep_register(srvsvc_v3_0_s_ifspec,
                        pServerBinding,
                        NULL,
                        (idl_char*)pszServiceName,
                        (unsigned32*)&dwRpcStatus);
    }
    DCETHREAD_CATCH_ALL(THIS_CATCH)
    {
        if ( dwRpcStatus == RPC_S_OK )
        {
            dwError = dcethread_exc_getstatus (THIS_CATCH);
            if(!dwError)
            {
                dwError = SRVSVC_ERROR_RPC_EXCEPTION_UPON_REGISTER;
            }
        }
    }
    DCETHREAD_ENDTRY;

    BAIL_ON_DCE_ERROR(dwError, dwRpcStatus);
    BAIL_ON_SRVSVC_ERROR(dwError);

    bEPRegistered = TRUE;
    SRVSVC_LOG_INFO("RPC Endpoint registered successfully.");

    *ppServerBinding = pServerBinding;

cleanup:
    // DCE/RPC runtime makes a copy of ncalrpc socket path internally
    // so it is safe to free it here
    LW_SAFE_FREE_MEMORY(lpcSocketPath);

    return dwError;

error:

    SRVSVC_LOG_ERROR("Failed to register RPC endpoint.  Error Code: [%u]\n", dwError);

    if (bEPRegistered)
    {
        DCETHREAD_TRY
        {
            DWORD tmpStatus = 0;
            rpc_ep_unregister(srvsvc_v3_0_s_ifspec,
                              pServerBinding,
                              NULL,
                              (unsigned32*)&tmpStatus);
        }
        DCETHREAD_CATCH_ALL(THIS_CATCH)
        DCETHREAD_ENDTRY;
    }

    if (bBound) {
        DCETHREAD_TRY
        {
            DWORD tmpStatus = 0;
            rpc_binding_vector_free(&pServerBinding,
                                    (unsigned32*)&tmpStatus);
        }
        DCETHREAD_CATCH_ALL(THIS_CATCH)
        DCETHREAD_ENDTRY;
    }

    if (bRegistered)
    {
        DCETHREAD_TRY
        {
            DWORD tmpStatus = 0;
            rpc_server_unregister_if (srvsvc_v3_0_s_ifspec,
                                      NULL,
                                      (unsigned32*)&tmpStatus);
        }
        DCETHREAD_CATCH_ALL(THIS_CATCH)
        DCETHREAD_ENDTRY;
    }

    *ppServerBinding = NULL;

    goto cleanup;
}
int main(int argc, char *argv[])
{
    unsigned32 status;
    rpc_binding_vector_p_t server_binding;
    char * string_binding;
    unsigned32 i;
    const char * protocol = NULL;
    const char * endpoint = NULL;
    int c;

    /*
     * Process the cmd line args
     */

    while ((c = getopt(argc, argv, "e:nut")) != EOF)
    {
        switch (c)
        {
        case 'e':
            endpoint = optarg;
            break;
        case 'n':
            protocol = PROTOCOL_NP;
            break;
        case 'u':
            protocol = PROTOCOL_UDP;
            break;
        case 't':
            protocol = PROTOCOL_TCP;
            break;
        default:
            usage();
        }
    }

#if 0
    if (endpoint && !protocol)
    {
        printf("ERROR: protocol is required when endpoint is specified\n");
        exit(1);
    }
#else
    if(!endpoint || !protocol)
    {
        usage();
        exit(1);
    }
#endif

#ifndef _WIN32
    /* Temporarily disable using all protocols because something is currently busted on Unix */
    if (!protocol)
    {
        protocol = PROTOCOL_TCP;
    }
#endif

    /*
     * Register the Interface with the local endpoint mapper (rpcd)
     */

    printf ("Registering server.... \n");
    rpc_server_register_if(echo_v1_0_s_ifspec,
                           NULL,
                           NULL,
                           &status);
    chk_dce_err(status, "rpc_server_register_if()", "", 1);

    printf("registered.\nPreparing binding handle...\n");

    bind_server(&server_binding, echo_v1_0_s_ifspec, protocol, endpoint);

    if(!endpoint)
    {
        /*
         * Register bindings with the endpoint mapper
         */
        printf("registering bindings with endpoint mapper\n");

        rpc_ep_register(echo_v1_0_s_ifspec,
                        server_binding,
                        NULL,
                        (unsigned char *)"QDA application server",
                        &status);
        chk_dce_err(status, "rpc_ep_register()", "", 1);
    }
    
    printf("registered.\n");

    /*
     * Print out the servers endpoints (TCP and UDP port numbers)
     */

    printf ("Server's communications endpoints are:\n");

    for (i=0; i<RPC_FIELD_COUNT(server_binding); i++)
    {
        rpc_binding_to_string_binding(RPC_FIELD_BINDING_H(server_binding)[i],
                                      (unsigned char **)&string_binding,
                                      &status);
        if (string_binding)
            printf("\t%s\n", string_binding);
    }

#ifndef _WIN32
    /*
     * Start the signal waiting thread in background. This thread will
     * Catch SIGINT and gracefully shutdown the server.
     */

    wait_for_signals();
#endif

    /*
     * Begin listening for calls
     */

    printf ("listening for calls....\n");

    DCETHREAD_TRY
    {
        rpc_server_listen(rpc_c_listen_max_calls_default, &status);
    }
    DCETHREAD_CATCH_ALL(THIS_CATCH)
    {
        printf ("Server stoppped listening\n");
    }
    DCETHREAD_ENDTRY;

    /*
     * If we reached this point, then the server was stopped, most likely
     * by the signal handler thread called rpc_mgmt_stop_server().
     * gracefully cleanup and unregister the bindings from the
     * endpoint mapper.
     */

#ifndef _WIN32
    /*
     * Kill the signal handling thread
     */

#endif

    if (!endpoint)
    {
        printf ("Unregistering server from the endpoint mapper....\n");
        rpc_ep_unregister(echo_v1_0_s_ifspec,
                          server_binding,
                          NULL,
                          &status);
        chk_dce_err(status, "rpc_ep_unregister()", "", 0);
    }

    /*
     * retire the binding information
     */

    printf("Cleaning up communications endpoints...\n");
    rpc_server_unregister_if(echo_v1_0_s_ifspec,
                             NULL,
                             &status);
    chk_dce_err(status, "rpc_server_unregister_if()", "", 0);

    exit(0);
}