]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3-rpc_server: Implement an endpoint monitor loop.
authorAndreas Schneider <asn@samba.org>
Thu, 10 Mar 2011 09:17:51 +0000 (10:17 +0100)
committerSimo Sorce <idra@samba.org>
Wed, 23 Mar 2011 16:19:22 +0000 (17:19 +0100)
source3/librpc/rpc/dcerpc_ep.c
source3/rpc_server/rpc_ep_setup.c

index 92c01a32bbc6e30c27e53fcf56ccc74b756caa41..1fce63acd212105cb1696827153155c9e0e67788 100644 (file)
@@ -289,7 +289,7 @@ static NTSTATUS ep_register(TALLOC_CTX *mem_ctx,
 
        if (pbh != NULL) {
                *pbh = talloc_move(mem_ctx, &h);
-               talloc_steal(mem_ctx, cli);
+               talloc_steal(*pbh, cli);
        }
 
 done:
index ddc655cb673e15b17fe519cfc3f882471e353346..836ef3024203819719c329b1221a930eb5aa01a8 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "includes.h"
 
+#include "../librpc/gen_ndr/ndr_epmapper_c.h"
 #include "../librpc/gen_ndr/srv_epmapper.h"
 #include "../librpc/gen_ndr/srv_srvsvc.h"
 #include "../librpc/gen_ndr/srv_winreg.h"
@@ -215,6 +216,9 @@ static NTSTATUS rpc_ep_setup_register(struct tevent_context *ev_ctx,
        return NT_STATUS_OK;
 }
 
+#define MONITOR_WAIT_TIME 15
+static void rpc_ep_setup_monitor_loop(struct tevent_req *subreq);
+
 static void rpc_ep_setup_register_loop(struct tevent_req *req)
 {
        struct rpc_ep_regsiter_state *state =
@@ -237,7 +241,16 @@ static void rpc_ep_setup_register_loop(struct tevent_req *req)
                                           state->port,
                                           &state->h);
        if (NT_STATUS_IS_OK(status)) {
-               talloc_free(state);
+               /* endpoint registered, monitor the connnection. */
+               req = tevent_wakeup_send(state->mem_ctx,
+                                        state->ev_ctx,
+                                        timeval_current_ofs(MONITOR_WAIT_TIME, 0));
+               if (tevent_req_nomem(state->mem_ctx, req)) {
+                       talloc_free(state);
+                       return;
+               }
+
+               tevent_req_set_callback(req, rpc_ep_setup_monitor_loop, state);
                return;
        }
 
@@ -293,6 +306,105 @@ static NTSTATUS rpc_ep_setup_try_register(TALLOC_CTX *mem_ctx,
        return status;
 }
 
+/*
+ * Monitor the connection to the endpoint mapper and if it goes away, try to
+ * register the endpoint.
+ */
+static void rpc_ep_setup_monitor_loop(struct tevent_req *subreq)
+{
+       struct rpc_ep_regsiter_state *state =
+               tevent_req_callback_data(subreq, struct rpc_ep_regsiter_state);
+       struct policy_handle entry_handle;
+       struct dcerpc_binding map_binding;
+       struct epm_twr_p_t towers[10];
+       struct epm_twr_t *map_tower;
+       uint32_t num_towers = 0;
+       struct GUID object;
+       NTSTATUS status;
+       uint32_t result = EPMAPPER_STATUS_CANT_PERFORM_OP;
+       TALLOC_CTX *tmp_ctx;
+       bool ok;
+
+       ZERO_STRUCT(object);
+       ZERO_STRUCT(entry_handle);
+
+       tmp_ctx = talloc_stackframe();
+       if (tmp_ctx == NULL) {
+               talloc_free(state);
+               return;
+       }
+
+       ok = tevent_wakeup_recv(subreq);
+       TALLOC_FREE(subreq);
+       if (!ok) {
+               talloc_free(state);
+               return;
+       }
+
+       /* Create map tower */
+       map_binding.transport = NCACN_NP;
+       map_binding.object = state->iface->syntax_id;
+       map_binding.host = "";
+       map_binding.endpoint = "";
+
+       map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
+       if (map_tower == NULL) {
+               talloc_free(tmp_ctx);
+               talloc_free(state);
+               return;
+       }
+
+       status = dcerpc_binding_build_tower(map_tower, &map_binding,
+                                           &map_tower->tower);
+       if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(tmp_ctx);
+               talloc_free(state);
+               return;
+       }
+
+       ok = false;
+       status = dcerpc_epm_Map(state->h,
+                               tmp_ctx,
+                               &object,
+                               map_tower,
+                               &entry_handle,
+                               10,
+                               &num_towers,
+                               towers,
+                               &result);
+       if (NT_STATUS_IS_OK(status)) {
+               ok = true;
+       }
+       if (result == EPMAPPER_STATUS_OK ||
+           result == EPMAPPER_STATUS_NO_MORE_ENTRIES) {
+               ok = true;
+       }
+       if (num_towers == 0) {
+               ok = false;
+       }
+
+       talloc_free(tmp_ctx);
+
+       subreq = tevent_wakeup_send(state->mem_ctx,
+                                   state->ev_ctx,
+                                   timeval_current_ofs(MONITOR_WAIT_TIME, 0));
+       if (tevent_req_nomem(state->mem_ctx, subreq)) {
+               talloc_free(state);
+               return;
+       }
+
+       if (ok) {
+               tevent_req_set_callback(subreq, rpc_ep_setup_monitor_loop, state);
+       } else {
+               TALLOC_FREE(state->h);
+               state->wait_time = 1;
+
+               tevent_req_set_callback(subreq, rpc_ep_setup_register_loop, state);
+       }
+
+       return;
+}
+
 static bool epmapper_init_cb(void *ptr)
 {
        struct dcesrv_ep_context *ep_ctx =