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/>.
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"
49 #include "rpc_server/rpc_sock_helper.h"
50 #include "rpc_server/rpc_service_setup.h"
51 #include "rpc_server/rpc_ep_register.h"
52 #include "rpc_server/rpc_server.h"
53 #include "rpc_server/epmapper/srv_epmapper.h"
55 static bool rpc_setup_epmapper(struct tevent_context *ev_ctx,
56 struct messaging_context *msg_ctx)
58 const char *rpcsrv_type;
61 /* start endpoint mapper only if enabled */
62 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
67 if (strcasecmp_m(rpcsrv_type, "none") == 0) {
68 status = rpc_epmapper_init(NULL);
69 if (!NT_STATUS_IS_OK(rpc_epmapper_init(NULL))) {
74 if (strcasecmp_m(rpcsrv_type, "embedded") == 0) {
75 status = rpc_setup_tcpip_sockets(ev_ctx,
80 if (!NT_STATUS_IS_OK(status)) {
88 static bool rpc_setup_winreg(struct tevent_context *ev_ctx,
89 struct messaging_context *msg_ctx,
90 const struct dcerpc_binding_vector *v)
92 const struct ndr_interface_table *t = &ndr_table_winreg;
93 const char *pipe_name = "winreg";
94 struct dcerpc_binding_vector *v2;
95 const char *rpcsrv_type;
99 status = rpc_winreg_init(NULL);
100 if (!NT_STATUS_IS_OK(status)) {
104 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
109 if (strcasecmp_m(rpcsrv_type, "embedded") == 0 ||
110 strcasecmp_m(rpcsrv_type, "daemon") == 0) {
111 v2 = dcerpc_binding_vector_dup(talloc_tos(), v);
116 status = dcerpc_binding_vector_replace_iface(t, v2);
117 if (!NT_STATUS_IS_OK(status)) {
121 status = dcerpc_binding_vector_add_np_default(t, v2);
122 if (!NT_STATUS_IS_OK(status)) {
126 ok = setup_dcerpc_ncalrpc_socket(ev_ctx,
134 status = dcerpc_binding_vector_add_unix(t, v2, pipe_name);
135 if (!NT_STATUS_IS_OK(status)) {
139 status = rpc_ep_register(ev_ctx,
143 if (!NT_STATUS_IS_OK(status)) {
151 static bool rpc_setup_srvsvc(struct tevent_context *ev_ctx,
152 struct messaging_context *msg_ctx,
153 const struct dcerpc_binding_vector *v)
155 const struct ndr_interface_table *t = &ndr_table_srvsvc;
156 const char *pipe_name = "srvsvc";
157 struct dcerpc_binding_vector *v2;
158 const char *rpcsrv_type;
162 status = rpc_srvsvc_init(NULL);
163 if (!NT_STATUS_IS_OK(status)) {
167 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
172 if (strcasecmp_m(rpcsrv_type, "embedded") == 0 ||
173 strcasecmp_m(rpcsrv_type, "daemon") == 0) {
174 v2 = dcerpc_binding_vector_dup(talloc_tos(), v);
179 status = dcerpc_binding_vector_replace_iface(t, v2);
180 if (!NT_STATUS_IS_OK(status)) {
184 status = dcerpc_binding_vector_add_np_default(t, v2);
185 if (!NT_STATUS_IS_OK(status)) {
189 ok = setup_dcerpc_ncalrpc_socket(ev_ctx,
197 status = dcerpc_binding_vector_add_unix(t, v2, pipe_name);
198 if (!NT_STATUS_IS_OK(status)) {
202 status = rpc_ep_register(ev_ctx,
206 if (!NT_STATUS_IS_OK(status)) {
214 static bool rpc_setup_lsarpc(struct tevent_context *ev_ctx,
215 struct messaging_context *msg_ctx,
216 const struct dcerpc_binding_vector *v)
218 const struct ndr_interface_table *t = &ndr_table_lsarpc;
219 const char *pipe_name = "lsarpc";
220 struct dcerpc_binding_vector *v2;
221 const char *rpcsrv_type;
225 status = rpc_lsarpc_init(NULL);
226 if (!NT_STATUS_IS_OK(status)) {
230 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
235 if (strcasecmp_m(rpcsrv_type, "embedded") == 0 ||
236 strcasecmp_m(rpcsrv_type, "daemon") == 0) {
237 v2 = dcerpc_binding_vector_dup(talloc_tos(), v);
242 status = dcerpc_binding_vector_replace_iface(t, v2);
243 if (!NT_STATUS_IS_OK(status)) {
247 status = dcerpc_binding_vector_add_np_default(t, v2);
248 if (!NT_STATUS_IS_OK(status)) {
252 ok = setup_dcerpc_ncalrpc_socket(ev_ctx,
260 status = dcerpc_binding_vector_add_unix(t, v2, pipe_name);
261 if (!NT_STATUS_IS_OK(status)) {
265 status = rpc_ep_register(ev_ctx,
269 if (!NT_STATUS_IS_OK(status)) {
277 static bool rpc_setup_samr(struct tevent_context *ev_ctx,
278 struct messaging_context *msg_ctx,
279 const struct dcerpc_binding_vector *v)
281 const struct ndr_interface_table *t = &ndr_table_samr;
282 const char *pipe_name = "samr";
283 struct dcerpc_binding_vector *v2;
284 const char *rpcsrv_type;
288 status = rpc_samr_init(NULL);
289 if (!NT_STATUS_IS_OK(status)) {
293 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
298 if (strcasecmp_m(rpcsrv_type, "embedded") == 0 ||
299 strcasecmp_m(rpcsrv_type, "daemon") == 0) {
300 v2 = dcerpc_binding_vector_dup(talloc_tos(), v);
305 status = dcerpc_binding_vector_replace_iface(t, v2);
306 if (!NT_STATUS_IS_OK(status)) {
310 status = dcerpc_binding_vector_add_np_default(t, v2);
311 if (!NT_STATUS_IS_OK(status)) {
315 ok = setup_dcerpc_ncalrpc_socket(ev_ctx,
323 status = dcerpc_binding_vector_add_unix(t, v2, pipe_name);
324 if (!NT_STATUS_IS_OK(status)) {
328 status = rpc_ep_register(ev_ctx,
332 if (!NT_STATUS_IS_OK(status)) {
340 static bool rpc_setup_netlogon(struct tevent_context *ev_ctx,
341 struct messaging_context *msg_ctx,
342 const struct dcerpc_binding_vector *v)
344 const struct ndr_interface_table *t = &ndr_table_netlogon;
345 const char *pipe_name = "netlogon";
346 struct dcerpc_binding_vector *v2;
347 const char *rpcsrv_type;
351 status = rpc_netlogon_init(NULL);
352 if (!NT_STATUS_IS_OK(status)) {
356 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
361 if (strcasecmp_m(rpcsrv_type, "embedded") == 0 ||
362 strcasecmp_m(rpcsrv_type, "daemon") == 0) {
363 v2 = dcerpc_binding_vector_dup(talloc_tos(), v);
368 status = dcerpc_binding_vector_replace_iface(t, v2);
369 if (!NT_STATUS_IS_OK(status)) {
373 status = dcerpc_binding_vector_add_np_default(t, v2);
374 if (!NT_STATUS_IS_OK(status)) {
378 ok = setup_dcerpc_ncalrpc_socket(ev_ctx,
386 status = dcerpc_binding_vector_add_unix(t, v2, pipe_name);
387 if (!NT_STATUS_IS_OK(status)) {
391 status = rpc_ep_register(ev_ctx,
395 if (!NT_STATUS_IS_OK(status)) {
403 static bool rpc_setup_netdfs(struct tevent_context *ev_ctx,
404 struct messaging_context *msg_ctx,
405 const struct dcerpc_binding_vector *v)
407 const struct ndr_interface_table *t = &ndr_table_netdfs;
408 const char *pipe_name = "netdfs";
409 struct dcerpc_binding_vector *v2;
410 const char *rpcsrv_type;
414 status = rpc_netdfs_init(NULL);
415 if (!NT_STATUS_IS_OK(status)) {
419 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
424 if (strcasecmp_m(rpcsrv_type, "embedded") == 0 ||
425 strcasecmp_m(rpcsrv_type, "daemon") == 0) {
426 v2 = dcerpc_binding_vector_dup(talloc_tos(), v);
431 status = dcerpc_binding_vector_replace_iface(t, v2);
432 if (!NT_STATUS_IS_OK(status)) {
436 status = dcerpc_binding_vector_add_np_default(t, v2);
437 if (!NT_STATUS_IS_OK(status)) {
441 ok = setup_dcerpc_ncalrpc_socket(ev_ctx,
449 status = dcerpc_binding_vector_add_unix(t, v2, pipe_name);
450 if (!NT_STATUS_IS_OK(status)) {
454 status = rpc_ep_register(ev_ctx,
458 if (!NT_STATUS_IS_OK(status)) {
467 static bool rpc_setup_rpcecho(struct tevent_context *ev_ctx,
468 struct messaging_context *msg_ctx,
469 const struct dcerpc_binding_vector *v)
471 const struct ndr_interface_table *t = &ndr_table_rpcecho;
472 const char *pipe_name = "rpcecho";
473 struct dcerpc_binding_vector *v2;
474 const char *rpcsrv_type;
478 status = rpc_rpcecho_init(NULL);
479 if (!NT_STATUS_IS_OK(status)) {
483 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
488 if (strcasecmp_m(rpcsrv_type, "embedded") == 0 ||
489 strcasecmp_m(rpcsrv_type, "daemon") == 0) {
490 v2 = dcerpc_binding_vector_dup(talloc_tos(), v);
495 status = dcerpc_binding_vector_replace_iface(t, v2);
496 if (!NT_STATUS_IS_OK(status)) {
500 status = dcerpc_binding_vector_add_np_default(t, v2);
501 if (!NT_STATUS_IS_OK(status)) {
505 ok = setup_dcerpc_ncalrpc_socket(ev_ctx,
513 status = dcerpc_binding_vector_add_unix(t, v2, pipe_name);
514 if (!NT_STATUS_IS_OK(status)) {
518 status = rpc_ep_register(ev_ctx,
522 if (!NT_STATUS_IS_OK(status)) {
531 static bool rpc_setup_dssetup(struct tevent_context *ev_ctx,
532 struct messaging_context *msg_ctx,
533 const struct dcerpc_binding_vector *v)
535 const struct ndr_interface_table *t = &ndr_table_dssetup;
536 const char *pipe_name = "dssetup";
537 struct dcerpc_binding_vector *v2;
538 const char *rpcsrv_type;
542 status = rpc_dssetup_init(NULL);
543 if (!NT_STATUS_IS_OK(status)) {
547 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
552 if (strcasecmp_m(rpcsrv_type, "embedded") == 0 ||
553 strcasecmp_m(rpcsrv_type, "daemon") == 0) {
554 v2 = dcerpc_binding_vector_dup(talloc_tos(), v);
559 status = dcerpc_binding_vector_replace_iface(t, v2);
560 if (!NT_STATUS_IS_OK(status)) {
564 status = dcerpc_binding_vector_add_np_default(t, v2);
565 if (!NT_STATUS_IS_OK(status)) {
569 ok = setup_dcerpc_ncalrpc_socket(ev_ctx,
577 status = dcerpc_binding_vector_add_unix(t, v2, pipe_name);
578 if (!NT_STATUS_IS_OK(status)) {
582 status = rpc_ep_register(ev_ctx,
586 if (!NT_STATUS_IS_OK(status)) {
594 static bool rpc_setup_wkssvc(struct tevent_context *ev_ctx,
595 struct messaging_context *msg_ctx,
596 const struct dcerpc_binding_vector *v)
598 const struct ndr_interface_table *t = &ndr_table_wkssvc;
599 const char *pipe_name = "wkssvc";
600 struct dcerpc_binding_vector *v2;
601 const char *rpcsrv_type;
605 status = rpc_wkssvc_init(NULL);
606 if (!NT_STATUS_IS_OK(status)) {
610 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
615 if (strcasecmp_m(rpcsrv_type, "embedded") == 0 ||
616 strcasecmp_m(rpcsrv_type, "daemon") == 0) {
617 v2 = dcerpc_binding_vector_dup(talloc_tos(), v);
622 status = dcerpc_binding_vector_replace_iface(t, v2);
623 if (!NT_STATUS_IS_OK(status)) {
627 status = dcerpc_binding_vector_add_np_default(t, v2);
628 if (!NT_STATUS_IS_OK(status)) {
632 ok = setup_dcerpc_ncalrpc_socket(ev_ctx,
640 status = dcerpc_binding_vector_add_unix(t, v2, pipe_name);
641 if (!NT_STATUS_IS_OK(status)) {
645 status = rpc_ep_register(ev_ctx,
649 if (!NT_STATUS_IS_OK(status)) {
657 static bool spoolss_init_cb(void *ptr)
659 struct messaging_context *msg_ctx =
660 talloc_get_type_abort(ptr, struct messaging_context);
664 * Migrate the printers first.
666 ok = nt_printing_tdb_migrate(msg_ctx);
674 static bool spoolss_shutdown_cb(void *ptr)
676 srv_spoolss_cleanup();
681 static bool rpc_setup_spoolss(struct tevent_context *ev_ctx,
682 struct messaging_context *msg_ctx)
684 const struct ndr_interface_table *t = &ndr_table_spoolss;
685 struct rpc_srv_callbacks spoolss_cb;
686 const char *rpcsrv_type;
687 struct dcerpc_binding_vector *v;
690 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
695 if (strcasecmp_m(rpcsrv_type, "embedded") == 0) {
696 spoolss_cb.init = spoolss_init_cb;
697 spoolss_cb.shutdown = spoolss_shutdown_cb;
698 spoolss_cb.private_data = msg_ctx;
700 status = rpc_spoolss_init(&spoolss_cb);
701 } else if (strcasecmp_m(rpcsrv_type, "daemon") == 0 ||
702 strcasecmp_m(rpcsrv_type, "external") == 0) {
703 status = rpc_spoolss_init(NULL);
705 if (!NT_STATUS_IS_OK(status)) {
709 if (strcasecmp_m(rpcsrv_type, "embedded")) {
710 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
715 if (strcasecmp_m(rpcsrv_type, "embedded") == 0 ||
716 strcasecmp_m(rpcsrv_type, "daemon") == 0) {
717 status = dcerpc_binding_vector_new(talloc_tos(), &v);
718 if (!NT_STATUS_IS_OK(status)) {
722 status = dcerpc_binding_vector_add_np_default(t, v);
723 if (!NT_STATUS_IS_OK(status)) {
727 status = rpc_ep_register(ev_ctx,
731 if (!NT_STATUS_IS_OK(status)) {
740 static bool svcctl_init_cb(void *ptr)
742 struct messaging_context *msg_ctx =
743 talloc_get_type_abort(ptr, struct messaging_context);
746 /* initialize the control hooks */
747 init_service_op_table();
749 ok = svcctl_init_winreg(msg_ctx);
757 static bool svcctl_shutdown_cb(void *ptr)
759 shutdown_service_op_table();
764 static bool rpc_setup_svcctl(struct tevent_context *ev_ctx,
765 struct messaging_context *msg_ctx)
767 const struct ndr_interface_table *t = &ndr_table_svcctl;
768 const char *pipe_name = "svcctl";
769 struct dcerpc_binding_vector *v;
770 struct rpc_srv_callbacks svcctl_cb;
771 const char *rpcsrv_type;
775 svcctl_cb.init = svcctl_init_cb;
776 svcctl_cb.shutdown = svcctl_shutdown_cb;
777 svcctl_cb.private_data = msg_ctx;
779 status = rpc_svcctl_init(&svcctl_cb);
780 if (!NT_STATUS_IS_OK(status)) {
784 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
789 if (strcasecmp_m(rpcsrv_type, "embedded") == 0 ||
790 strcasecmp_m(rpcsrv_type, "daemon") == 0) {
791 status = dcerpc_binding_vector_new(talloc_tos(), &v);
792 if (!NT_STATUS_IS_OK(status)) {
796 status = dcerpc_binding_vector_add_np_default(t, v);
797 if (!NT_STATUS_IS_OK(status)) {
801 ok = setup_dcerpc_ncalrpc_socket(ev_ctx,
809 status = dcerpc_binding_vector_add_unix(t, v, pipe_name);
810 if (!NT_STATUS_IS_OK(status)) {
814 status = rpc_ep_register(ev_ctx,
818 if (!NT_STATUS_IS_OK(status)) {
826 static bool rpc_setup_ntsvcs(struct tevent_context *ev_ctx,
827 struct messaging_context *msg_ctx)
829 const struct ndr_interface_table *t = &ndr_table_ntsvcs;
830 struct dcerpc_binding_vector *v;
831 const char *rpcsrv_type;
834 status = rpc_ntsvcs_init(NULL);
835 if (!NT_STATUS_IS_OK(status)) {
839 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
844 if (strcasecmp_m(rpcsrv_type, "embedded") == 0 ||
845 strcasecmp_m(rpcsrv_type, "daemon") == 0) {
846 status = dcerpc_binding_vector_new(talloc_tos(), &v);
847 if (!NT_STATUS_IS_OK(status)) {
851 status = dcerpc_binding_vector_add_np_default(t, v);
852 if (!NT_STATUS_IS_OK(status)) {
856 status = rpc_ep_register(ev_ctx,
860 if (!NT_STATUS_IS_OK(status)) {
868 static bool eventlog_init_cb(void *ptr)
870 struct messaging_context *msg_ctx =
871 talloc_get_type_abort(ptr, struct messaging_context);
874 ok = eventlog_init_winreg(msg_ctx);
882 static bool rpc_setup_eventlog(struct tevent_context *ev_ctx,
883 struct messaging_context *msg_ctx)
885 const struct ndr_interface_table *t = &ndr_table_eventlog;
886 struct rpc_srv_callbacks eventlog_cb;
887 struct dcerpc_binding_vector *v;
888 const char *rpcsrv_type;
891 eventlog_cb.init = eventlog_init_cb;
892 eventlog_cb.shutdown = NULL;
893 eventlog_cb.private_data = msg_ctx;
895 status = rpc_eventlog_init(&eventlog_cb);
896 if (!NT_STATUS_IS_OK(status)) {
900 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
905 if (strcasecmp_m(rpcsrv_type, "embedded") == 0 ||
906 strcasecmp_m(rpcsrv_type, "daemon") == 0) {
907 status = dcerpc_binding_vector_new(talloc_tos(), &v);
908 if (!NT_STATUS_IS_OK(status)) {
912 status = dcerpc_binding_vector_add_np_default(t, v);
913 if (!NT_STATUS_IS_OK(status)) {
917 status = rpc_ep_register(ev_ctx,
921 if (!NT_STATUS_IS_OK(status)) {
929 static bool rpc_setup_initshutdown(struct tevent_context *ev_ctx,
930 struct messaging_context *msg_ctx)
932 const struct ndr_interface_table *t = &ndr_table_initshutdown;
933 struct dcerpc_binding_vector *v;
934 const char *rpcsrv_type;
937 status = rpc_initshutdown_init(NULL);
938 if (!NT_STATUS_IS_OK(status)) {
942 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
947 if (strcasecmp_m(rpcsrv_type, "embedded") == 0 ||
948 strcasecmp_m(rpcsrv_type, "daemon") == 0) {
949 status = dcerpc_binding_vector_new(talloc_tos(), &v);
950 if (!NT_STATUS_IS_OK(status)) {
954 status = dcerpc_binding_vector_add_np_default(t, v);
955 if (!NT_STATUS_IS_OK(status)) {
959 status = rpc_ep_register(ev_ctx,
963 if (!NT_STATUS_IS_OK(status)) {
971 bool dcesrv_ep_setup(struct tevent_context *ev_ctx,
972 struct messaging_context *msg_ctx)
974 struct dcerpc_binding_vector *v;
979 tmp_ctx = talloc_stackframe();
980 if (tmp_ctx == NULL) {
984 status = dcerpc_binding_vector_new(tmp_ctx,
986 if (!NT_STATUS_IS_OK(status)) {
991 ok = rpc_setup_epmapper(ev_ctx, msg_ctx);
996 status = rpc_setup_tcpip_sockets(ev_ctx,
1001 if (!NT_STATUS_IS_OK(status)) {
1006 ok = rpc_setup_winreg(ev_ctx, msg_ctx, v);
1011 ok = rpc_setup_srvsvc(ev_ctx, msg_ctx, v);
1016 ok = rpc_setup_lsarpc(ev_ctx, msg_ctx, v);
1021 ok = rpc_setup_samr(ev_ctx, msg_ctx, v);
1026 ok = rpc_setup_netlogon(ev_ctx, msg_ctx, v);
1031 ok = rpc_setup_netdfs(ev_ctx, msg_ctx, v);
1037 ok = rpc_setup_rpcecho(ev_ctx, msg_ctx, v);
1043 ok = rpc_setup_dssetup(ev_ctx, msg_ctx, v);
1048 ok = rpc_setup_wkssvc(ev_ctx, msg_ctx, v);
1053 ok = rpc_setup_spoolss(ev_ctx, msg_ctx);
1058 ok = rpc_setup_svcctl(ev_ctx, msg_ctx);
1063 ok = rpc_setup_ntsvcs(ev_ctx, msg_ctx);
1068 ok = rpc_setup_eventlog(ev_ctx, msg_ctx);
1073 ok = rpc_setup_initshutdown(ev_ctx, msg_ctx);
1079 talloc_free(tmp_ctx);
1083 /* vim: set ts=8 sw=8 noet cindent ft=c.doxygen: */