s3: Fix a winbind race leading to 100% CPU
[Samba.git] / source3 / rpc_server / rpc_ep_setup.c
blobee2aed0b20b2e41c3b58df70595ceca28b36cadf
1 /*
2 * Unix SMB/CIFS implementation.
4 * SMBD RPC service callbacks
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/>.
22 #include "includes.h"
23 #include "ntdomain.h"
25 #include "../librpc/gen_ndr/ndr_epmapper_c.h"
26 #include "../librpc/gen_ndr/srv_epmapper.h"
27 #include "../librpc/gen_ndr/srv_srvsvc.h"
28 #include "../librpc/gen_ndr/srv_winreg.h"
29 #include "../librpc/gen_ndr/srv_dfs.h"
30 #include "../librpc/gen_ndr/srv_dssetup.h"
31 #include "../librpc/gen_ndr/srv_echo.h"
32 #include "../librpc/gen_ndr/srv_eventlog.h"
33 #include "../librpc/gen_ndr/srv_initshutdown.h"
34 #include "../librpc/gen_ndr/srv_lsa.h"
35 #include "../librpc/gen_ndr/srv_netlogon.h"
36 #include "../librpc/gen_ndr/srv_ntsvcs.h"
37 #include "../librpc/gen_ndr/srv_samr.h"
38 #include "../librpc/gen_ndr/srv_spoolss.h"
39 #include "../librpc/gen_ndr/srv_svcctl.h"
40 #include "../librpc/gen_ndr/srv_wkssvc.h"
42 #include "printing/nt_printing_migrate_internal.h"
43 #include "rpc_server/eventlog/srv_eventlog_reg.h"
44 #include "rpc_server/svcctl/srv_svcctl_reg.h"
45 #include "rpc_server/spoolss/srv_spoolss_nt.h"
46 #include "rpc_server/svcctl/srv_svcctl_nt.h"
48 #include "librpc/rpc/dcerpc_ep.h"
50 #include "rpc_server/rpc_ep_setup.h"
51 #include "rpc_server/rpc_server.h"
52 #include "rpc_server/epmapper/srv_epmapper.h"
54 struct dcesrv_ep_context {
55 struct tevent_context *ev_ctx;
56 struct messaging_context *msg_ctx;
59 static uint16_t _open_sockets(struct tevent_context *ev_ctx,
60 struct messaging_context *msg_ctx,
61 struct ndr_syntax_id syntax_id,
62 uint16_t port)
64 uint32_t num_ifs = iface_count();
65 uint32_t i;
66 uint16_t p = 0;
68 if (lp_interfaces() && lp_bind_interfaces_only()) {
70 * We have been given an interfaces line, and been told to only
71 * bind to those interfaces. Create a socket per interface and
72 * bind to only these.
75 /* Now open a listen socket for each of the interfaces. */
76 for(i = 0; i < num_ifs; i++) {
77 const struct sockaddr_storage *ifss =
78 iface_n_sockaddr_storage(i);
80 p = setup_dcerpc_ncacn_tcpip_socket(ev_ctx,
81 msg_ctx,
82 syntax_id,
83 ifss,
84 port);
85 if (p == 0) {
86 return 0;
88 port = p;
90 } else {
91 const char *sock_addr = lp_socket_address();
92 const char *sock_ptr;
93 char *sock_tok;
95 if (strequal(sock_addr, "0.0.0.0") ||
96 strequal(sock_addr, "::")) {
97 #if HAVE_IPV6
98 sock_addr = "::";
99 #else
100 sock_addr = "0.0.0.0";
101 #endif
104 for (sock_ptr = sock_addr;
105 next_token_talloc(talloc_tos(), &sock_ptr, &sock_tok, " \t,");
107 struct sockaddr_storage ss;
109 /* open an incoming socket */
110 if (!interpret_string_addr(&ss,
111 sock_tok,
112 AI_NUMERICHOST|AI_PASSIVE)) {
113 continue;
116 p = setup_dcerpc_ncacn_tcpip_socket(ev_ctx,
117 msg_ctx,
118 syntax_id,
119 &ss,
120 port);
121 if (p == 0) {
122 return 0;
124 port = p;
128 return p;
131 static void rpc_ep_setup_register_loop(struct tevent_req *subreq);
132 static NTSTATUS rpc_ep_setup_try_register(TALLOC_CTX *mem_ctx,
133 struct tevent_context *ev_ctx,
134 struct messaging_context *msg_ctx,
135 const struct ndr_interface_table *iface,
136 const char *ncalrpc,
137 uint16_t port,
138 struct dcerpc_binding_handle **pbh);
140 struct rpc_ep_regsiter_state {
141 struct dcerpc_binding_handle *h;
143 TALLOC_CTX *mem_ctx;
144 struct tevent_context *ev_ctx;
145 struct messaging_context *msg_ctx;
147 const struct ndr_interface_table *iface;
149 const char *ncalrpc;
150 uint16_t port;
152 uint32_t wait_time;
155 NTSTATUS rpc_ep_setup_register(struct tevent_context *ev_ctx,
156 struct messaging_context *msg_ctx,
157 const struct ndr_interface_table *iface,
158 const char *ncalrpc,
159 uint16_t port)
161 struct rpc_ep_regsiter_state *state;
162 struct tevent_req *req;
164 state = talloc(ev_ctx, struct rpc_ep_regsiter_state);
165 if (state == NULL) {
166 return NT_STATUS_NO_MEMORY;
169 state->mem_ctx = talloc_named(state,
171 "ep %s %p",
172 iface->name, state);
173 if (state->mem_ctx == NULL) {
174 talloc_free(state);
175 return NT_STATUS_NO_MEMORY;
178 state->wait_time = 1;
179 state->ev_ctx = ev_ctx;
180 state->msg_ctx = msg_ctx;
181 state->iface = iface;
182 state->ncalrpc = talloc_strdup(state, ncalrpc);
183 state->port = port;
185 req = tevent_wakeup_send(state->mem_ctx,
186 state->ev_ctx,
187 timeval_current_ofs(1, 0));
188 if (tevent_req_nomem(state->mem_ctx, req)) {
189 talloc_free(state);
190 return NT_STATUS_NO_MEMORY;
193 tevent_req_set_callback(req, rpc_ep_setup_register_loop, state);
195 return NT_STATUS_OK;
198 #define MONITOR_WAIT_TIME 15
199 static void rpc_ep_setup_monitor_loop(struct tevent_req *subreq);
201 static void rpc_ep_setup_register_loop(struct tevent_req *subreq)
203 struct rpc_ep_regsiter_state *state =
204 tevent_req_callback_data(subreq, struct rpc_ep_regsiter_state);
205 NTSTATUS status;
206 bool ok;
208 ok = tevent_wakeup_recv(subreq);
209 TALLOC_FREE(subreq);
210 if (!ok) {
211 talloc_free(state);
212 return;
215 status = rpc_ep_setup_try_register(state->mem_ctx,
216 state->ev_ctx,
217 state->msg_ctx,
218 state->iface,
219 state->ncalrpc,
220 state->port,
221 &state->h);
222 if (NT_STATUS_IS_OK(status)) {
223 /* endpoint registered, monitor the connnection. */
224 subreq = tevent_wakeup_send(state->mem_ctx,
225 state->ev_ctx,
226 timeval_current_ofs(MONITOR_WAIT_TIME, 0));
227 if (tevent_req_nomem(state->mem_ctx, subreq)) {
228 talloc_free(state);
229 return;
232 tevent_req_set_callback(subreq, rpc_ep_setup_monitor_loop, state);
233 return;
236 state->wait_time = state->wait_time * 2;
237 if (state->wait_time > 16) {
238 DEBUG(0, ("Failed to register endpoint '%s'!\n",
239 state->iface->name));
240 state->wait_time = 16;
243 subreq = tevent_wakeup_send(state->mem_ctx,
244 state->ev_ctx,
245 timeval_current_ofs(state->wait_time, 0));
246 if (tevent_req_nomem(state->mem_ctx, subreq)) {
247 talloc_free(state);
248 return;
251 tevent_req_set_callback(subreq, rpc_ep_setup_register_loop, state);
252 return;
255 static NTSTATUS rpc_ep_setup_try_register(TALLOC_CTX *mem_ctx,
256 struct tevent_context *ev_ctx,
257 struct messaging_context *msg_ctx,
258 const struct ndr_interface_table *iface,
259 const char *ncalrpc,
260 uint16_t port,
261 struct dcerpc_binding_handle **pbh)
263 struct dcerpc_binding_vector *v = NULL;
264 NTSTATUS status;
266 status = dcerpc_binding_vector_create(mem_ctx,
267 iface,
268 port,
269 ncalrpc,
270 &v);
271 if (!NT_STATUS_IS_OK(status)) {
272 return status;
275 status = dcerpc_ep_register(mem_ctx,
276 iface,
278 &iface->syntax_id.uuid,
279 iface->name,
280 pbh);
281 talloc_free(v);
282 if (!NT_STATUS_IS_OK(status)) {
283 return status;
286 return status;
290 * Monitor the connection to the endpoint mapper and if it goes away, try to
291 * register the endpoint.
293 static void rpc_ep_setup_monitor_loop(struct tevent_req *subreq)
295 struct rpc_ep_regsiter_state *state =
296 tevent_req_callback_data(subreq, struct rpc_ep_regsiter_state);
297 struct policy_handle entry_handle;
298 struct dcerpc_binding map_binding;
299 struct epm_twr_p_t towers[10];
300 struct epm_twr_t *map_tower;
301 uint32_t num_towers = 0;
302 struct GUID object;
303 NTSTATUS status;
304 uint32_t result = EPMAPPER_STATUS_CANT_PERFORM_OP;
305 TALLOC_CTX *tmp_ctx;
306 bool ok;
308 ZERO_STRUCT(object);
309 ZERO_STRUCT(entry_handle);
311 tmp_ctx = talloc_stackframe();
312 if (tmp_ctx == NULL) {
313 talloc_free(state);
314 return;
317 ok = tevent_wakeup_recv(subreq);
318 TALLOC_FREE(subreq);
319 if (!ok) {
320 talloc_free(state);
321 return;
324 /* Create map tower */
325 map_binding.transport = NCACN_NP;
326 map_binding.object = state->iface->syntax_id;
327 map_binding.host = "";
328 map_binding.endpoint = "";
330 map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
331 if (map_tower == NULL) {
332 talloc_free(tmp_ctx);
333 talloc_free(state);
334 return;
337 status = dcerpc_binding_build_tower(map_tower, &map_binding,
338 &map_tower->tower);
339 if (!NT_STATUS_IS_OK(status)) {
340 talloc_free(tmp_ctx);
341 talloc_free(state);
342 return;
345 ok = false;
346 status = dcerpc_epm_Map(state->h,
347 tmp_ctx,
348 &object,
349 map_tower,
350 &entry_handle,
352 &num_towers,
353 towers,
354 &result);
355 if (NT_STATUS_IS_OK(status)) {
356 ok = true;
358 if (result == EPMAPPER_STATUS_OK ||
359 result == EPMAPPER_STATUS_NO_MORE_ENTRIES) {
360 ok = true;
362 if (num_towers == 0) {
363 ok = false;
366 talloc_free(tmp_ctx);
368 subreq = tevent_wakeup_send(state->mem_ctx,
369 state->ev_ctx,
370 timeval_current_ofs(MONITOR_WAIT_TIME, 0));
371 if (tevent_req_nomem(state->mem_ctx, subreq)) {
372 talloc_free(state);
373 return;
376 if (ok) {
377 tevent_req_set_callback(subreq, rpc_ep_setup_monitor_loop, state);
378 } else {
379 TALLOC_FREE(state->h);
380 state->wait_time = 1;
382 tevent_req_set_callback(subreq, rpc_ep_setup_register_loop, state);
385 return;
388 static bool epmapper_init_cb(void *ptr)
390 struct dcesrv_ep_context *ep_ctx =
391 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
392 uint16_t port;
394 port = _open_sockets(ep_ctx->ev_ctx,
395 ep_ctx->msg_ctx,
396 ndr_table_epmapper.syntax_id,
397 135);
398 if (port == 135) {
399 return true;
402 return false;
405 static bool epmapper_shutdown_cb(void *ptr)
407 srv_epmapper_cleanup();
409 return true;
412 static bool winreg_init_cb(void *ptr)
414 struct dcesrv_ep_context *ep_ctx =
415 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
416 struct ndr_syntax_id abstract_syntax = ndr_table_winreg.syntax_id;
417 const char *pipe_name = "winreg";
418 const char *rpcsrv_type;
419 uint16_t port;
421 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
422 "rpc_server",
423 "epmapper",
424 "none");
426 if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
427 StrCaseCmp(rpcsrv_type, "daemon") == 0) {
428 NTSTATUS status;
429 bool ok;
431 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
432 ep_ctx->msg_ctx,
433 abstract_syntax,
434 pipe_name,
435 NULL);
436 if (!ok) {
437 return false;
439 port = _open_sockets(ep_ctx->ev_ctx,
440 ep_ctx->msg_ctx,
441 abstract_syntax,
443 if (port == 0) {
444 return false;
447 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
448 ep_ctx->msg_ctx,
449 &ndr_table_winreg,
450 pipe_name,
451 port);
452 if (!NT_STATUS_IS_OK(status)) {
453 return false;
457 return true;
460 static bool srvsvc_init_cb(void *ptr)
462 struct dcesrv_ep_context *ep_ctx =
463 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
464 struct ndr_syntax_id abstract_syntax = ndr_table_srvsvc.syntax_id;
465 const char *pipe_name = "srvsvc";
466 const char *rpcsrv_type;
467 uint16_t port;
469 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
470 "rpc_server",
471 "epmapper",
472 "none");
474 if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
475 StrCaseCmp(rpcsrv_type, "daemon") == 0) {
476 NTSTATUS status;
477 bool ok;
479 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
480 ep_ctx->msg_ctx,
481 abstract_syntax,
482 pipe_name,
483 NULL);
484 if (!ok) {
485 return false;
488 port = _open_sockets(ep_ctx->ev_ctx,
489 ep_ctx->msg_ctx,
490 abstract_syntax,
492 if (port == 0) {
493 return false;
496 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
497 ep_ctx->msg_ctx,
498 &ndr_table_srvsvc,
499 pipe_name,
500 port);
501 if (!NT_STATUS_IS_OK(status)) {
502 return false;
506 return true;
509 static bool lsarpc_init_cb(void *ptr)
511 struct dcesrv_ep_context *ep_ctx =
512 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
513 struct ndr_syntax_id abstract_syntax = ndr_table_lsarpc.syntax_id;
514 const char *pipe_name = "lsarpc";
515 const char *rpcsrv_type;
516 uint16_t port;
518 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
519 "rpc_server",
520 "epmapper",
521 "none");
523 if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
524 StrCaseCmp(rpcsrv_type, "daemon") == 0) {
525 NTSTATUS status;
526 bool ok;
528 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
529 ep_ctx->msg_ctx,
530 abstract_syntax,
531 pipe_name,
532 NULL);
533 if (!ok) {
534 return false;
537 port = _open_sockets(ep_ctx->ev_ctx,
538 ep_ctx->msg_ctx,
539 abstract_syntax,
541 if (port == 0) {
542 return false;
545 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
546 ep_ctx->msg_ctx,
547 &ndr_table_lsarpc,
548 pipe_name,
549 port);
550 if (!NT_STATUS_IS_OK(status)) {
551 return false;
555 return true;
558 static bool samr_init_cb(void *ptr)
560 struct dcesrv_ep_context *ep_ctx =
561 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
562 struct ndr_syntax_id abstract_syntax = ndr_table_samr.syntax_id;
563 const char *pipe_name = "samr";
564 const char *rpcsrv_type;
565 uint16_t port;
567 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
568 "rpc_server",
569 "epmapper",
570 "none");
572 if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
573 StrCaseCmp(rpcsrv_type, "daemon") == 0) {
574 NTSTATUS status;
575 bool ok;
577 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
578 ep_ctx->msg_ctx,
579 abstract_syntax,
580 pipe_name,
581 NULL);
582 if (!ok) {
583 return false;
586 port = _open_sockets(ep_ctx->ev_ctx,
587 ep_ctx->msg_ctx,
588 abstract_syntax,
590 if (port == 0) {
591 return false;
594 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
595 ep_ctx->msg_ctx,
596 &ndr_table_samr,
597 pipe_name,
598 port);
599 if (!NT_STATUS_IS_OK(status)) {
600 return false;
604 return true;
607 static bool netlogon_init_cb(void *ptr)
609 struct dcesrv_ep_context *ep_ctx =
610 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
611 struct ndr_syntax_id abstract_syntax = ndr_table_netlogon.syntax_id;
612 const char *pipe_name = "netlogon";
613 const char *rpcsrv_type;
614 uint16_t port;
616 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
617 "rpc_server",
618 "epmapper",
619 "none");
621 if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
622 StrCaseCmp(rpcsrv_type, "daemon") == 0) {
623 NTSTATUS status;
624 bool ok;
626 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
627 ep_ctx->msg_ctx,
628 abstract_syntax,
629 pipe_name,
630 NULL);
631 if (!ok) {
632 return false;
635 port = _open_sockets(ep_ctx->ev_ctx,
636 ep_ctx->msg_ctx,
637 abstract_syntax,
639 if (port == 0) {
640 return false;
643 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
644 ep_ctx->msg_ctx,
645 &ndr_table_netlogon,
646 pipe_name,
647 port);
648 if (!NT_STATUS_IS_OK(status)) {
649 return false;
653 return true;
656 static bool spoolss_init_cb(void *ptr)
658 struct dcesrv_ep_context *ep_ctx =
659 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
660 const char *rpcsrv_type;
661 bool ok;
663 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
664 "rpc_server",
665 "epmapper",
666 "none");
669 * Migrate the printers first.
671 ok = nt_printing_tdb_migrate(ep_ctx->msg_ctx);
672 if (!ok) {
673 return false;
676 if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
677 StrCaseCmp(rpcsrv_type, "daemon") == 0) {
678 NTSTATUS status;
680 status =rpc_ep_setup_register(ep_ctx->ev_ctx,
681 ep_ctx->msg_ctx,
682 &ndr_table_spoolss,
683 "spoolss",
685 if (!NT_STATUS_IS_OK(status)) {
686 return false;
690 return true;
693 static bool spoolss_shutdown_cb(void *ptr)
695 srv_spoolss_cleanup();
697 return true;
700 static bool svcctl_init_cb(void *ptr)
702 struct dcesrv_ep_context *ep_ctx =
703 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
704 const char *rpcsrv_type;
705 bool ok;
707 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
708 "rpc_server",
709 "epmapper",
710 "none");
712 ok = svcctl_init_winreg(ep_ctx->msg_ctx);
713 if (!ok) {
714 return false;
717 /* initialize the control hooks */
718 init_service_op_table();
720 if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
721 StrCaseCmp(rpcsrv_type, "daemon") == 0) {
722 NTSTATUS status;
724 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
725 ep_ctx->msg_ctx,
726 &ndr_table_svcctl,
727 "svcctl",
729 if (!NT_STATUS_IS_OK(status)) {
730 return false;
734 return true;
737 static bool svcctl_shutdown_cb(void *ptr)
739 shutdown_service_op_table();
741 return true;
744 static bool ntsvcs_init_cb(void *ptr)
746 struct dcesrv_ep_context *ep_ctx =
747 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
748 const char *rpcsrv_type;
750 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
751 "rpc_server",
752 "epmapper",
753 "none");
755 if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
756 StrCaseCmp(rpcsrv_type, "daemon") == 0) {
757 NTSTATUS status;
759 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
760 ep_ctx->msg_ctx,
761 &ndr_table_ntsvcs,
762 "ntsvcs",
764 if (!NT_STATUS_IS_OK(status)) {
765 return false;
769 return true;
772 static bool eventlog_init_cb(void *ptr)
774 struct dcesrv_ep_context *ep_ctx =
775 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
776 const char *rpcsrv_type;
777 bool ok;
779 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
780 "rpc_server",
781 "epmapper",
782 "none");
784 ok = eventlog_init_winreg(ep_ctx->msg_ctx);
785 if (!ok) {
786 return false;
789 if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
790 StrCaseCmp(rpcsrv_type, "daemon") == 0) {
791 NTSTATUS status;
793 status =rpc_ep_setup_register(ep_ctx->ev_ctx,
794 ep_ctx->msg_ctx,
795 &ndr_table_eventlog,
796 "eventlog",
798 if (!NT_STATUS_IS_OK(status)) {
799 return false;
803 return true;
806 static bool initshutdown_init_cb(void *ptr)
808 struct dcesrv_ep_context *ep_ctx =
809 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
810 const char *rpcsrv_type;
812 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
813 "rpc_server",
814 "epmapper",
815 "none");
817 if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
818 StrCaseCmp(rpcsrv_type, "daemon") == 0) {
819 NTSTATUS status;
821 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
822 ep_ctx->msg_ctx,
823 &ndr_table_initshutdown,
824 "initshutdown",
826 if (!NT_STATUS_IS_OK(status)) {
827 return false;
831 return true;
834 #ifdef DEVELOPER
835 static bool rpcecho_init_cb(void *ptr) {
836 struct dcesrv_ep_context *ep_ctx =
837 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
838 const char *rpcsrv_type;
839 uint16_t port;
841 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
842 "rpc_server",
843 "epmapper",
844 "none");
846 if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
847 StrCaseCmp(rpcsrv_type, "daemon") == 0) {
848 NTSTATUS status;
850 port = _open_sockets(ep_ctx->ev_ctx,
851 ep_ctx->msg_ctx,
852 ndr_table_rpcecho.syntax_id,
854 if (port == 0) {
855 return false;
858 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
859 ep_ctx->msg_ctx,
860 &ndr_table_rpcecho,
861 "rpcecho",
862 port);
863 if (!NT_STATUS_IS_OK(status)) {
864 return false;
868 return true;
871 #endif
873 static bool netdfs_init_cb(void *ptr)
875 struct dcesrv_ep_context *ep_ctx =
876 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
877 struct ndr_syntax_id abstract_syntax = ndr_table_netdfs.syntax_id;
878 const char *pipe_name = "netdfs";
879 const char *rpcsrv_type;
880 uint16_t port;
882 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
883 "rpc_server",
884 "epmapper",
885 "none");
886 if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
887 StrCaseCmp(rpcsrv_type, "daemon") == 0) {
888 NTSTATUS status;
889 bool ok;
891 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
892 ep_ctx->msg_ctx,
893 abstract_syntax,
894 pipe_name,
895 NULL);
896 if (!ok) {
897 return false;
900 port = _open_sockets(ep_ctx->ev_ctx,
901 ep_ctx->msg_ctx,
902 abstract_syntax,
904 if (port == 0) {
905 return false;
908 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
909 ep_ctx->msg_ctx,
910 &ndr_table_netdfs,
911 pipe_name,
912 port);
913 if (!NT_STATUS_IS_OK(status)) {
914 return false;
918 return true;
921 static bool dssetup_init_cb(void *ptr)
923 struct dcesrv_ep_context *ep_ctx =
924 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
925 struct ndr_syntax_id abstract_syntax = ndr_table_dssetup.syntax_id;
926 const char *pipe_name = "dssetup";
927 const char *rpcsrv_type;
928 uint16_t port;
930 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
931 "rpc_server",
932 "epmapper",
933 "none");
935 if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
936 StrCaseCmp(rpcsrv_type, "daemon") == 0) {
937 NTSTATUS status;
938 bool ok;
940 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
941 ep_ctx->msg_ctx,
942 abstract_syntax,
943 pipe_name,
944 NULL);
945 if (!ok) {
946 return false;
949 port = _open_sockets(ep_ctx->ev_ctx,
950 ep_ctx->msg_ctx,
951 abstract_syntax,
953 if (port == 0) {
954 return false;
957 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
958 ep_ctx->msg_ctx,
959 &ndr_table_dssetup,
960 "dssetup",
961 port);
962 if (!NT_STATUS_IS_OK(status)) {
963 return false;
967 return true;
970 static bool wkssvc_init_cb(void *ptr)
972 struct dcesrv_ep_context *ep_ctx =
973 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
974 struct ndr_syntax_id abstract_syntax = ndr_table_wkssvc.syntax_id;
975 const char *pipe_name = "wkssvc";
976 const char *rpcsrv_type;
977 uint16_t port;
979 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
980 "rpc_server",
981 "epmapper",
982 "none");
983 if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
984 StrCaseCmp(rpcsrv_type, "daemon") == 0) {
985 NTSTATUS status;
986 bool ok;
988 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
989 ep_ctx->msg_ctx,
990 abstract_syntax,
991 pipe_name,
992 NULL);
993 if (!ok) {
994 return false;
997 port = _open_sockets(ep_ctx->ev_ctx,
998 ep_ctx->msg_ctx,
999 abstract_syntax,
1001 if (port == 0) {
1002 return false;
1005 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
1006 ep_ctx->msg_ctx,
1007 &ndr_table_wkssvc,
1008 "wkssvc",
1009 port);
1010 if (!NT_STATUS_IS_OK(status)) {
1011 return false;
1015 return true;
1018 bool dcesrv_ep_setup(struct tevent_context *ev_ctx,
1019 struct messaging_context *msg_ctx)
1021 struct dcesrv_ep_context *ep_ctx;
1023 struct rpc_srv_callbacks epmapper_cb;
1025 struct rpc_srv_callbacks winreg_cb;
1026 struct rpc_srv_callbacks srvsvc_cb;
1028 struct rpc_srv_callbacks lsarpc_cb;
1029 struct rpc_srv_callbacks samr_cb;
1030 struct rpc_srv_callbacks netlogon_cb;
1032 struct rpc_srv_callbacks spoolss_cb;
1033 struct rpc_srv_callbacks svcctl_cb;
1034 struct rpc_srv_callbacks ntsvcs_cb;
1035 struct rpc_srv_callbacks eventlog_cb;
1036 struct rpc_srv_callbacks initshutdown_cb;
1037 struct rpc_srv_callbacks netdfs_cb;
1038 #ifdef DEVELOPER
1039 struct rpc_srv_callbacks rpcecho_cb;
1040 #endif
1041 struct rpc_srv_callbacks dssetup_cb;
1042 struct rpc_srv_callbacks wkssvc_cb;
1044 const char *rpcsrv_type;
1046 ep_ctx = talloc(ev_ctx, struct dcesrv_ep_context);
1047 if (ep_ctx == NULL) {
1048 return false;
1051 ep_ctx->ev_ctx = ev_ctx;
1052 ep_ctx->msg_ctx = msg_ctx;
1054 /* start endpoint mapper only if enabled */
1055 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
1056 "rpc_server",
1057 "epmapper",
1058 "none");
1059 if (StrCaseCmp(rpcsrv_type, "embedded") == 0) {
1060 epmapper_cb.init = epmapper_init_cb;
1061 epmapper_cb.shutdown = epmapper_shutdown_cb;
1062 epmapper_cb.private_data = ep_ctx;
1064 if (!NT_STATUS_IS_OK(rpc_epmapper_init(&epmapper_cb))) {
1065 return false;
1067 } else if (StrCaseCmp(rpcsrv_type, "daemon") == 0) {
1068 if (!NT_STATUS_IS_OK(rpc_epmapper_init(NULL))) {
1069 return false;
1073 winreg_cb.init = winreg_init_cb;
1074 winreg_cb.shutdown = NULL;
1075 winreg_cb.private_data = ep_ctx;
1076 if (!NT_STATUS_IS_OK(rpc_winreg_init(&winreg_cb))) {
1077 return false;
1080 srvsvc_cb.init = srvsvc_init_cb;
1081 srvsvc_cb.shutdown = NULL;
1082 srvsvc_cb.private_data = ep_ctx;
1083 if (!NT_STATUS_IS_OK(rpc_srvsvc_init(&srvsvc_cb))) {
1084 return false;
1088 lsarpc_cb.init = lsarpc_init_cb;
1089 lsarpc_cb.shutdown = NULL;
1090 lsarpc_cb.private_data = ep_ctx;
1091 if (!NT_STATUS_IS_OK(rpc_lsarpc_init(&lsarpc_cb))) {
1092 return false;
1095 samr_cb.init = samr_init_cb;
1096 samr_cb.shutdown = NULL;
1097 samr_cb.private_data = ep_ctx;
1098 if (!NT_STATUS_IS_OK(rpc_samr_init(&samr_cb))) {
1099 return false;
1102 netlogon_cb.init = netlogon_init_cb;
1103 netlogon_cb.shutdown = NULL;
1104 netlogon_cb.private_data = ep_ctx;
1105 if (!NT_STATUS_IS_OK(rpc_netlogon_init(&netlogon_cb))) {
1106 return false;
1109 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
1110 "rpc_server",
1111 "spoolss",
1112 "embedded");
1113 if (StrCaseCmp(rpcsrv_type, "embedded") == 0) {
1114 spoolss_cb.init = spoolss_init_cb;
1115 spoolss_cb.shutdown = spoolss_shutdown_cb;
1116 spoolss_cb.private_data = ep_ctx;
1117 if (!NT_STATUS_IS_OK(rpc_spoolss_init(&spoolss_cb))) {
1118 return false;
1120 } else if (StrCaseCmp(rpcsrv_type, "daemon") == 0 ||
1121 StrCaseCmp(rpcsrv_type, "external") == 0) {
1122 if (!NT_STATUS_IS_OK(rpc_spoolss_init(NULL))) {
1123 return false;
1127 svcctl_cb.init = svcctl_init_cb;
1128 svcctl_cb.shutdown = svcctl_shutdown_cb;
1129 svcctl_cb.private_data = ep_ctx;
1130 if (!NT_STATUS_IS_OK(rpc_svcctl_init(&svcctl_cb))) {
1131 return false;
1134 ntsvcs_cb.init = ntsvcs_init_cb;
1135 ntsvcs_cb.shutdown = NULL;
1136 ntsvcs_cb.private_data = ep_ctx;
1137 if (!NT_STATUS_IS_OK(rpc_ntsvcs_init(&ntsvcs_cb))) {
1138 return false;
1141 eventlog_cb.init = eventlog_init_cb;
1142 eventlog_cb.shutdown = NULL;
1143 eventlog_cb.private_data = ep_ctx;
1144 if (!NT_STATUS_IS_OK(rpc_eventlog_init(&eventlog_cb))) {
1145 return false;
1148 initshutdown_cb.init = initshutdown_init_cb;
1149 initshutdown_cb.shutdown = NULL;
1150 initshutdown_cb.private_data = ep_ctx;
1151 if (!NT_STATUS_IS_OK(rpc_initshutdown_init(&initshutdown_cb))) {
1152 return false;
1155 netdfs_cb.init = netdfs_init_cb;
1156 netdfs_cb.shutdown = NULL;
1157 netdfs_cb.private_data = ep_ctx;
1158 if (!NT_STATUS_IS_OK(rpc_netdfs_init(&netdfs_cb))) {
1159 return false;
1162 #ifdef DEVELOPER
1163 rpcecho_cb.init = rpcecho_init_cb;
1164 rpcecho_cb.shutdown = NULL;
1165 rpcecho_cb.private_data = ep_ctx;
1166 if (!NT_STATUS_IS_OK(rpc_rpcecho_init(&rpcecho_cb))) {
1167 return false;
1169 #endif
1171 dssetup_cb.init = dssetup_init_cb;
1172 dssetup_cb.shutdown = NULL;
1173 dssetup_cb.private_data = ep_ctx;
1174 if (!NT_STATUS_IS_OK(rpc_dssetup_init(&dssetup_cb))) {
1175 return false;
1178 wkssvc_cb.init = wkssvc_init_cb;
1179 wkssvc_cb.shutdown = NULL;
1180 wkssvc_cb.private_data = ep_ctx;
1181 if (!NT_STATUS_IS_OK(rpc_wkssvc_init(&wkssvc_cb))) {
1182 return false;
1185 return true;
1188 /* vim: set ts=8 sw=8 noet cindent ft=c.doxygen: */