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
,
37 struct dcerpc_binding_handle
**pbh
);
39 struct rpc_ep_regsiter_state
{
40 struct dcerpc_binding_handle
*h
;
43 struct tevent_context
*ev_ctx
;
44 struct messaging_context
*msg_ctx
;
46 const struct ndr_interface_table
*iface
;
54 NTSTATUS
rpc_ep_register(struct tevent_context
*ev_ctx
,
55 struct messaging_context
*msg_ctx
,
56 const struct ndr_interface_table
*iface
,
60 struct rpc_ep_regsiter_state
*state
;
61 struct tevent_req
*req
;
63 state
= talloc(ev_ctx
, struct rpc_ep_regsiter_state
);
65 return NT_STATUS_NO_MEMORY
;
68 state
->mem_ctx
= talloc_named(state
,
72 if (state
->mem_ctx
== NULL
) {
74 return NT_STATUS_NO_MEMORY
;
78 state
->ev_ctx
= ev_ctx
;
79 state
->msg_ctx
= msg_ctx
;
81 state
->ncalrpc
= talloc_strdup(state
, ncalrpc
);
84 req
= tevent_wakeup_send(state
->mem_ctx
,
86 timeval_current_ofs(1, 0));
87 if (tevent_req_nomem(state
->mem_ctx
, req
)) {
89 return NT_STATUS_NO_MEMORY
;
92 tevent_req_set_callback(req
, rpc_ep_register_loop
, state
);
97 #define MONITOR_WAIT_TIME 15
98 static void rpc_ep_monitor_loop(struct tevent_req
*subreq
);
100 static void rpc_ep_register_loop(struct tevent_req
*subreq
)
102 struct rpc_ep_regsiter_state
*state
=
103 tevent_req_callback_data(subreq
, struct rpc_ep_regsiter_state
);
107 ok
= tevent_wakeup_recv(subreq
);
114 status
= rpc_ep_try_register(state
->mem_ctx
,
121 if (NT_STATUS_IS_OK(status
)) {
122 /* endpoint registered, monitor the connnection. */
123 subreq
= tevent_wakeup_send(state
->mem_ctx
,
125 timeval_current_ofs(MONITOR_WAIT_TIME
, 0));
126 if (tevent_req_nomem(state
->mem_ctx
, subreq
)) {
131 tevent_req_set_callback(subreq
, rpc_ep_monitor_loop
, state
);
135 state
->wait_time
= state
->wait_time
* 2;
136 if (state
->wait_time
> 16) {
137 DEBUG(0, ("Failed to register endpoint '%s'!\n",
138 state
->iface
->name
));
139 state
->wait_time
= 16;
142 subreq
= tevent_wakeup_send(state
->mem_ctx
,
144 timeval_current_ofs(state
->wait_time
, 0));
145 if (tevent_req_nomem(state
->mem_ctx
, subreq
)) {
150 tevent_req_set_callback(subreq
, rpc_ep_register_loop
, state
);
154 static NTSTATUS
rpc_ep_try_register(TALLOC_CTX
*mem_ctx
,
155 struct tevent_context
*ev_ctx
,
156 struct messaging_context
*msg_ctx
,
157 const struct ndr_interface_table
*iface
,
160 struct dcerpc_binding_handle
**pbh
)
162 struct dcerpc_binding_vector
*v
= NULL
;
165 status
= dcerpc_binding_vector_create(mem_ctx
,
170 if (!NT_STATUS_IS_OK(status
)) {
174 status
= dcerpc_ep_register(mem_ctx
,
178 &iface
->syntax_id
.uuid
,
182 if (!NT_STATUS_IS_OK(status
)) {
190 * Monitor the connection to the endpoint mapper and if it goes away, try to
191 * register the endpoint.
193 static void rpc_ep_monitor_loop(struct tevent_req
*subreq
)
195 struct rpc_ep_regsiter_state
*state
=
196 tevent_req_callback_data(subreq
, struct rpc_ep_regsiter_state
);
197 struct policy_handle entry_handle
;
198 struct dcerpc_binding map_binding
;
199 struct epm_twr_p_t towers
[10];
200 struct epm_twr_t
*map_tower
;
201 uint32_t num_towers
= 0;
204 uint32_t result
= EPMAPPER_STATUS_CANT_PERFORM_OP
;
209 ZERO_STRUCT(entry_handle
);
211 tmp_ctx
= talloc_stackframe();
212 if (tmp_ctx
== NULL
) {
217 ok
= tevent_wakeup_recv(subreq
);
224 /* Create map tower */
225 map_binding
.transport
= NCACN_NP
;
226 map_binding
.object
= state
->iface
->syntax_id
;
227 map_binding
.host
= "";
228 map_binding
.endpoint
= "";
230 map_tower
= talloc_zero(tmp_ctx
, struct epm_twr_t
);
231 if (map_tower
== NULL
) {
232 talloc_free(tmp_ctx
);
237 status
= dcerpc_binding_build_tower(map_tower
, &map_binding
,
239 if (!NT_STATUS_IS_OK(status
)) {
240 talloc_free(tmp_ctx
);
246 status
= dcerpc_epm_Map(state
->h
,
255 if (NT_STATUS_IS_OK(status
)) {
258 if (result
== EPMAPPER_STATUS_OK
||
259 result
== EPMAPPER_STATUS_NO_MORE_ENTRIES
) {
262 if (num_towers
== 0) {
266 talloc_free(tmp_ctx
);
268 subreq
= tevent_wakeup_send(state
->mem_ctx
,
270 timeval_current_ofs(MONITOR_WAIT_TIME
, 0));
271 if (tevent_req_nomem(state
->mem_ctx
, subreq
)) {
277 tevent_req_set_callback(subreq
, rpc_ep_monitor_loop
, state
);
279 TALLOC_FREE(state
->h
);
280 state
->wait_time
= 1;
282 tevent_req_set_callback(subreq
, rpc_ep_register_loop
, state
);