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_regsiter_state
{
39 struct dcerpc_binding_handle
*h
;
42 struct tevent_context
*ev_ctx
;
43 struct messaging_context
*msg_ctx
;
45 const struct ndr_interface_table
*iface
;
46 const struct dcerpc_binding_vector
*vector
;
51 NTSTATUS
rpc_ep_register(struct tevent_context
*ev_ctx
,
52 struct messaging_context
*msg_ctx
,
53 const struct ndr_interface_table
*iface
,
54 const struct dcerpc_binding_vector
*v
)
56 struct rpc_ep_regsiter_state
*state
;
57 struct tevent_req
*req
;
59 state
= talloc(ev_ctx
, struct rpc_ep_regsiter_state
);
61 return NT_STATUS_NO_MEMORY
;
64 state
->mem_ctx
= talloc_named(state
,
68 if (state
->mem_ctx
== NULL
) {
70 return NT_STATUS_NO_MEMORY
;
74 state
->ev_ctx
= ev_ctx
;
75 state
->msg_ctx
= msg_ctx
;
77 state
->vector
= dcerpc_binding_vector_dup(state
, v
);
78 if (state
->vector
== NULL
) {
80 return NT_STATUS_NO_MEMORY
;
83 req
= tevent_wakeup_send(state
->mem_ctx
,
85 timeval_current_ofs(1, 0));
86 if (tevent_req_nomem(state
->mem_ctx
, req
)) {
88 return NT_STATUS_NO_MEMORY
;
91 tevent_req_set_callback(req
, rpc_ep_register_loop
, state
);
96 #define MONITOR_WAIT_TIME 30
97 static void rpc_ep_monitor_loop(struct tevent_req
*subreq
);
99 static void rpc_ep_register_loop(struct tevent_req
*subreq
)
101 struct rpc_ep_regsiter_state
*state
=
102 tevent_req_callback_data(subreq
, struct rpc_ep_regsiter_state
);
106 ok
= tevent_wakeup_recv(subreq
);
113 status
= rpc_ep_try_register(state
->mem_ctx
,
119 if (NT_STATUS_IS_OK(status
)) {
120 /* endpoint registered, monitor the connnection. */
121 subreq
= tevent_wakeup_send(state
->mem_ctx
,
123 timeval_current_ofs(MONITOR_WAIT_TIME
, 0));
124 if (tevent_req_nomem(state
->mem_ctx
, subreq
)) {
129 tevent_req_set_callback(subreq
, rpc_ep_monitor_loop
, state
);
133 state
->wait_time
= state
->wait_time
* 2;
134 if (state
->wait_time
> 16) {
135 DEBUG(0, ("Failed to register endpoint '%s'!\n",
136 state
->iface
->name
));
137 state
->wait_time
= 16;
140 subreq
= tevent_wakeup_send(state
->mem_ctx
,
142 timeval_current_ofs(state
->wait_time
, 0));
143 if (tevent_req_nomem(state
->mem_ctx
, subreq
)) {
148 tevent_req_set_callback(subreq
, rpc_ep_register_loop
, state
);
152 static NTSTATUS
rpc_ep_try_register(TALLOC_CTX
*mem_ctx
,
153 struct tevent_context
*ev_ctx
,
154 struct messaging_context
*msg_ctx
,
155 const struct ndr_interface_table
*iface
,
156 const struct dcerpc_binding_vector
*v
,
157 struct dcerpc_binding_handle
**pbh
)
161 status
= dcerpc_ep_register(mem_ctx
,
165 &iface
->syntax_id
.uuid
,
168 if (!NT_STATUS_IS_OK(status
)) {
176 * Monitor the connection to the endpoint mapper and if it goes away, try to
177 * register the endpoint.
179 static void rpc_ep_monitor_loop(struct tevent_req
*subreq
)
181 struct rpc_ep_regsiter_state
*state
=
182 tevent_req_callback_data(subreq
, struct rpc_ep_regsiter_state
);
183 struct policy_handle entry_handle
;
184 struct dcerpc_binding map_binding
;
185 struct epm_twr_p_t towers
[10];
186 struct epm_twr_t
*map_tower
;
187 uint32_t num_towers
= 0;
190 uint32_t result
= EPMAPPER_STATUS_CANT_PERFORM_OP
;
195 ZERO_STRUCT(entry_handle
);
197 tmp_ctx
= talloc_stackframe();
198 if (tmp_ctx
== NULL
) {
203 ok
= tevent_wakeup_recv(subreq
);
210 /* Create map tower */
211 map_binding
.transport
= NCACN_NP
;
212 map_binding
.object
= state
->iface
->syntax_id
;
213 map_binding
.host
= "";
214 map_binding
.endpoint
= "";
216 map_tower
= talloc_zero(tmp_ctx
, struct epm_twr_t
);
217 if (map_tower
== NULL
) {
218 talloc_free(tmp_ctx
);
223 status
= dcerpc_binding_build_tower(map_tower
, &map_binding
,
225 if (!NT_STATUS_IS_OK(status
)) {
226 talloc_free(tmp_ctx
);
232 status
= dcerpc_epm_Map(state
->h
,
241 if (NT_STATUS_IS_OK(status
)) {
244 if (result
== EPMAPPER_STATUS_OK
||
245 result
== EPMAPPER_STATUS_NO_MORE_ENTRIES
) {
248 if (num_towers
== 0) {
252 dcerpc_epm_LookupHandleFree(state
->h
,
256 talloc_free(tmp_ctx
);
258 subreq
= tevent_wakeup_send(state
->mem_ctx
,
260 timeval_current_ofs(MONITOR_WAIT_TIME
, 0));
261 if (tevent_req_nomem(state
->mem_ctx
, subreq
)) {
267 tevent_req_set_callback(subreq
, rpc_ep_monitor_loop
, state
);
269 TALLOC_FREE(state
->h
);
270 state
->wait_time
= 1;
272 tevent_req_set_callback(subreq
, rpc_ep_register_loop
, state
);