2 * Unix SMB/CIFS implementation.
4 * RPC Endpoint Registration
6 * Copyright (c) 2011 Andreas Schneider <asn@samba.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
25 #include "../librpc/gen_ndr/ndr_epmapper_c.h"
27 #include "librpc/rpc/dcerpc_ep.h"
28 #include "rpc_server/rpc_ep_register.h"
30 static void rpc_ep_register_loop(struct tevent_req *subreq);
31 static NTSTATUS rpc_ep_try_register(TALLOC_CTX *mem_ctx,
32 struct tevent_context *ev_ctx,
33 struct messaging_context *msg_ctx,
34 const struct ndr_interface_table *iface,
35 const struct dcerpc_binding_vector *v,
36 struct dcerpc_binding_handle **pbh);
38 struct rpc_ep_register_state {
39 struct dcerpc_binding_handle *h;
41 struct tevent_context *ev_ctx;
42 struct messaging_context *msg_ctx;
44 const struct ndr_interface_table *iface;
45 const struct dcerpc_binding_vector *vector;
50 NTSTATUS rpc_ep_register(struct tevent_context *ev_ctx,
51 struct messaging_context *msg_ctx,
52 const struct ndr_interface_table *iface,
53 const struct dcerpc_binding_vector *v)
55 struct rpc_ep_register_state *state;
56 struct tevent_req *req;
58 state = talloc(ev_ctx, struct rpc_ep_register_state);
60 return NT_STATUS_NO_MEMORY;
64 state->ev_ctx = ev_ctx;
65 state->msg_ctx = msg_ctx;
67 state->vector = dcerpc_binding_vector_dup(state, v);
68 if (state->vector == NULL) {
70 return NT_STATUS_NO_MEMORY;
73 req = tevent_wakeup_send(state,
75 timeval_current_ofs(1, 0));
78 return NT_STATUS_NO_MEMORY;
81 tevent_req_set_callback(req, rpc_ep_register_loop, state);
86 #define MONITOR_WAIT_TIME 30
87 static void rpc_ep_monitor_loop(struct tevent_req *subreq);
89 static void rpc_ep_register_loop(struct tevent_req *subreq)
91 struct rpc_ep_register_state *state =
92 tevent_req_callback_data(subreq, struct rpc_ep_register_state);
96 ok = tevent_wakeup_recv(subreq);
103 status = rpc_ep_try_register(state,
109 if (NT_STATUS_IS_OK(status)) {
110 /* endpoint registered, monitor the connnection. */
111 subreq = tevent_wakeup_send(state,
113 timeval_current_ofs(MONITOR_WAIT_TIME, 0));
114 if (subreq == NULL) {
119 tevent_req_set_callback(subreq, rpc_ep_monitor_loop, state);
123 state->wait_time = state->wait_time * 2;
124 if (state->wait_time > 16) {
125 DEBUG(0, ("Failed to register endpoint '%s'!\n",
126 state->iface->name));
127 state->wait_time = 16;
130 subreq = tevent_wakeup_send(state,
132 timeval_current_ofs(state->wait_time, 0));
133 if (subreq == NULL) {
138 tevent_req_set_callback(subreq, rpc_ep_register_loop, state);
142 static NTSTATUS rpc_ep_try_register(TALLOC_CTX *mem_ctx,
143 struct tevent_context *ev_ctx,
144 struct messaging_context *msg_ctx,
145 const struct ndr_interface_table *iface,
146 const struct dcerpc_binding_vector *v,
147 struct dcerpc_binding_handle **pbh)
151 status = dcerpc_ep_register(mem_ctx,
155 &iface->syntax_id.uuid,
158 if (!NT_STATUS_IS_OK(status)) {
166 * Monitor the connection to the endpoint mapper and if it goes away, try to
167 * register the endpoint.
169 static void rpc_ep_monitor_loop(struct tevent_req *subreq)
171 struct rpc_ep_register_state *state =
172 tevent_req_callback_data(subreq, struct rpc_ep_register_state);
173 struct policy_handle entry_handle;
174 struct dcerpc_binding map_binding;
175 struct epm_twr_p_t towers[10];
176 struct epm_twr_t *map_tower;
177 uint32_t num_towers = 0;
180 uint32_t result = EPMAPPER_STATUS_CANT_PERFORM_OP;
185 ZERO_STRUCT(entry_handle);
187 tmp_ctx = talloc_stackframe();
188 if (tmp_ctx == NULL) {
193 ok = tevent_wakeup_recv(subreq);
200 /* Create map tower */
201 map_binding.transport = NCACN_NP;
202 map_binding.object = state->iface->syntax_id;
203 map_binding.host = "";
204 map_binding.endpoint = "";
206 map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
207 if (map_tower == NULL) {
208 talloc_free(tmp_ctx);
213 status = dcerpc_binding_build_tower(map_tower, &map_binding,
215 if (!NT_STATUS_IS_OK(status)) {
216 talloc_free(tmp_ctx);
222 status = dcerpc_epm_Map(state->h,
231 if (NT_STATUS_IS_OK(status)) {
234 if (result == EPMAPPER_STATUS_OK ||
235 result == EPMAPPER_STATUS_NO_MORE_ENTRIES) {
238 if (num_towers == 0) {
242 dcerpc_epm_LookupHandleFree(state->h,
246 talloc_free(tmp_ctx);
248 subreq = tevent_wakeup_send(state,
250 timeval_current_ofs(MONITOR_WAIT_TIME, 0));
251 if (subreq == NULL) {
257 tevent_req_set_callback(subreq, rpc_ep_monitor_loop, state);
259 TALLOC_FREE(state->h);
260 state->wait_time = 1;
262 tevent_req_set_callback(subreq, rpc_ep_register_loop, state);