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
);
196 talloc_free(tmp_ctx
);
201 /* Create map tower */
202 status
= dcerpc_parse_binding(tmp_ctx
, "ncacn_np:", &map_binding
);
203 if (!NT_STATUS_IS_OK(status
)) {
204 talloc_free(tmp_ctx
);
209 status
= dcerpc_binding_set_abstract_syntax(map_binding
,
210 &state
->iface
->syntax_id
);
211 if (!NT_STATUS_IS_OK(status
)) {
212 talloc_free(tmp_ctx
);
217 map_tower
= talloc_zero(tmp_ctx
, struct epm_twr_t
);
218 if (map_tower
== NULL
) {
219 talloc_free(tmp_ctx
);
224 status
= dcerpc_binding_build_tower(map_tower
, map_binding
,
226 if (!NT_STATUS_IS_OK(status
)) {
227 talloc_free(tmp_ctx
);
233 status
= dcerpc_epm_Map(state
->h
,
242 if (NT_STATUS_IS_OK(status
)) {
245 if (result
== EPMAPPER_STATUS_OK
||
246 result
== EPMAPPER_STATUS_NO_MORE_ENTRIES
) {
249 if (num_towers
== 0) {
253 dcerpc_epm_LookupHandleFree(state
->h
,
257 talloc_free(tmp_ctx
);
259 subreq
= tevent_wakeup_send(state
,
261 timeval_current_ofs(MONITOR_WAIT_TIME
, 0));
262 if (subreq
== NULL
) {
268 tevent_req_set_callback(subreq
, rpc_ep_monitor_loop
, state
);
270 TALLOC_FREE(state
->h
);
271 state
->wait_time
= 1;
273 tevent_req_set_callback(subreq
, rpc_ep_register_loop
, state
);