s3-rpc_server: Added a memory context to the ep regsiter state.
[ddiss/samba.git] / source3 / rpc_server / rpc_ep_setup.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *
4  *  SMBD RPC service callbacks
5  *
6  *  Copyright (c) 2011      Andreas Schneider <asn@samba.org>
7  *
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.
12  *
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.
17  *
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/>.
20  */
21
22 #include "includes.h"
23
24 #include "../librpc/gen_ndr/srv_epmapper.h"
25 #include "../librpc/gen_ndr/srv_srvsvc.h"
26 #include "../librpc/gen_ndr/srv_winreg.h"
27 #include "../librpc/gen_ndr/srv_dfs.h"
28 #include "../librpc/gen_ndr/srv_dssetup.h"
29 #include "../librpc/gen_ndr/srv_echo.h"
30 #include "../librpc/gen_ndr/srv_eventlog.h"
31 #include "../librpc/gen_ndr/srv_initshutdown.h"
32 #include "../librpc/gen_ndr/srv_lsa.h"
33 #include "../librpc/gen_ndr/srv_netlogon.h"
34 #include "../librpc/gen_ndr/srv_ntsvcs.h"
35 #include "../librpc/gen_ndr/srv_samr.h"
36 #include "../librpc/gen_ndr/srv_spoolss.h"
37 #include "../librpc/gen_ndr/srv_svcctl.h"
38 #include "../librpc/gen_ndr/srv_wkssvc.h"
39
40 #include "printing/nt_printing_migrate.h"
41 #include "rpc_server/eventlog/srv_eventlog_reg.h"
42 #include "rpc_server/svcctl/srv_svcctl_reg.h"
43
44 #include "librpc/rpc/dcerpc_ep.h"
45
46 #include "rpc_server/rpc_ep_setup.h"
47 #include "rpc_server/rpc_server.h"
48 #include "rpc_server/epmapper/srv_epmapper.h"
49
50 struct dcesrv_ep_context {
51         struct tevent_context *ev_ctx;
52         struct messaging_context *msg_ctx;
53 };
54
55 static uint16_t _open_sockets(struct tevent_context *ev_ctx,
56                               struct messaging_context *msg_ctx,
57                               struct ndr_syntax_id syntax_id,
58                               uint16_t port)
59 {
60         uint32_t num_ifs = iface_count();
61         uint32_t i;
62         uint16_t p = 0;
63
64         if (lp_interfaces() && lp_bind_interfaces_only()) {
65                 /*
66                  * We have been given an interfaces line, and been told to only
67                  * bind to those interfaces. Create a socket per interface and
68                  * bind to only these.
69                  */
70
71                 /* Now open a listen socket for each of the interfaces. */
72                 for(i = 0; i < num_ifs; i++) {
73                         const struct sockaddr_storage *ifss =
74                                         iface_n_sockaddr_storage(i);
75
76                         p = setup_dcerpc_ncacn_tcpip_socket(ev_ctx,
77                                                             msg_ctx,
78                                                             syntax_id,
79                                                             ifss,
80                                                             port);
81                         if (p == 0) {
82                                 return 0;
83                         }
84                         port = p;
85                 }
86         } else {
87                 const char *sock_addr = lp_socket_address();
88                 const char *sock_ptr;
89                 char *sock_tok;
90
91                 if (strequal(sock_addr, "0.0.0.0") ||
92                     strequal(sock_addr, "::")) {
93 #if HAVE_IPV6
94                         sock_addr = "::";
95 #else
96                         sock_addr = "0.0.0.0";
97 #endif
98                 }
99
100                 for (sock_ptr = sock_addr;
101                      next_token_talloc(talloc_tos(), &sock_ptr, &sock_tok, " \t,");
102                     ) {
103                         struct sockaddr_storage ss;
104
105                         /* open an incoming socket */
106                         if (!interpret_string_addr(&ss,
107                                                    sock_tok,
108                                                    AI_NUMERICHOST|AI_PASSIVE)) {
109                                 continue;
110                         }
111
112                         p = setup_dcerpc_ncacn_tcpip_socket(ev_ctx,
113                                                             msg_ctx,
114                                                             syntax_id,
115                                                             &ss,
116                                                             port);
117                         if (p == 0) {
118                                 return 0;
119                         }
120                         port = p;
121                 }
122         }
123
124         return p;
125 }
126
127 static NTSTATUS _rpc_ep_unregister(const struct ndr_interface_table *iface)
128 {
129         struct dcerpc_binding_vector *v = NULL;
130         NTSTATUS status;
131
132         status = dcerpc_binding_vector_create(talloc_tos(),
133                                               iface,
134                                               0,
135                                               NULL,
136                                               &v);
137         if (!NT_STATUS_IS_OK(status)) {
138                 return status;
139         }
140
141         status = dcerpc_ep_unregister(iface,
142                                       v,
143                                       &iface->syntax_id.uuid);
144         if (!NT_STATUS_IS_OK(status)) {
145                 return status;
146         }
147
148         return status;
149 }
150
151 static void rpc_ep_setup_register_loop(struct tevent_req *subreq);
152 static NTSTATUS rpc_ep_setup_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 char *name,
157                                           uint16_t port,
158                                           struct dcerpc_binding_handle **pbh);
159
160 struct rpc_ep_regsiter_state {
161         struct dcerpc_binding_handle *h;
162
163         TALLOC_CTX *mem_ctx;
164         struct tevent_context *ev_ctx;
165         struct messaging_context *msg_ctx;
166
167         const struct ndr_interface_table *iface;
168
169         const char *ncalrpc;
170         uint16_t port;
171
172         uint32_t wait_time;
173 };
174
175 static NTSTATUS rpc_ep_setup_register(struct tevent_context *ev_ctx,
176                                       struct messaging_context *msg_ctx,
177                                       const struct ndr_interface_table *iface,
178                                       const char *ncalrpc,
179                                       uint16_t port)
180 {
181         struct rpc_ep_regsiter_state *state;
182         struct tevent_req *req;
183
184         state = talloc(ev_ctx, struct rpc_ep_regsiter_state);
185         if (state == NULL) {
186                 return NT_STATUS_NO_MEMORY;
187         }
188
189         state->mem_ctx = talloc_named(state,
190                                       0,
191                                       "ep %s %p",
192                                       iface->name, state);
193         if (state->mem_ctx == NULL) {
194                 talloc_free(state);
195                 return NT_STATUS_NO_MEMORY;
196         }
197
198         state->wait_time = 1;
199         state->ev_ctx = ev_ctx;
200         state->msg_ctx = msg_ctx;
201         state->iface = iface;
202         state->ncalrpc = talloc_strdup(state, ncalrpc);
203         state->port = port;
204
205         req = tevent_wakeup_send(state->mem_ctx,
206                                  state->ev_ctx,
207                                  timeval_current_ofs(1, 0));
208         if (tevent_req_nomem(state->mem_ctx, req)) {
209                 talloc_free(state);
210                 return NT_STATUS_NO_MEMORY;
211         }
212
213         tevent_req_set_callback(req, rpc_ep_setup_register_loop, state);
214
215         return NT_STATUS_OK;
216 }
217
218 static void rpc_ep_setup_register_loop(struct tevent_req *req)
219 {
220         struct rpc_ep_regsiter_state *state =
221                 tevent_req_callback_data(req, struct rpc_ep_regsiter_state);
222         NTSTATUS status;
223         bool ok;
224
225         ok = tevent_wakeup_recv(req);
226         TALLOC_FREE(req);
227         if (!ok) {
228                 talloc_free(state);
229                 return;
230         }
231
232         status = rpc_ep_setup_try_register(state->mem_ctx,
233                                            state->ev_ctx,
234                                            state->msg_ctx,
235                                            state->iface,
236                                            state->ncalrpc,
237                                            state->port,
238                                            &state->h);
239         if (NT_STATUS_IS_OK(status)) {
240                 talloc_free(state);
241                 return;
242         }
243
244         state->wait_time = state->wait_time * 2;
245         if (state->wait_time > 16) {
246                 talloc_free(state);
247                 return;
248         }
249
250         req = tevent_wakeup_send(state->mem_ctx,
251                                  state->ev_ctx,
252                                  timeval_current_ofs(state->wait_time, 0));
253         if (tevent_req_nomem(state->mem_ctx, req)) {
254                 talloc_free(state);
255                 return;
256         }
257
258         tevent_req_set_callback(req, rpc_ep_setup_register_loop, state);
259         return;
260 }
261
262 static NTSTATUS rpc_ep_setup_try_register(TALLOC_CTX *mem_ctx,
263                                           struct tevent_context *ev_ctx,
264                                           struct messaging_context *msg_ctx,
265                                           const struct ndr_interface_table *iface,
266                                           const char *name,
267                                           uint16_t port,
268                                           struct dcerpc_binding_handle **pbh)
269 {
270         struct dcerpc_binding_vector *v = NULL;
271         NTSTATUS status;
272
273         status = dcerpc_binding_vector_create(mem_ctx,
274                                               iface,
275                                               port,
276                                               name,
277                                               &v);
278         if (!NT_STATUS_IS_OK(status)) {
279                 return status;
280         }
281
282         status = dcerpc_ep_register(mem_ctx,
283                                     iface,
284                                     v,
285                                     &iface->syntax_id.uuid,
286                                     name,
287                                     pbh);
288         talloc_free(v);
289         if (!NT_STATUS_IS_OK(status)) {
290                 return status;
291         }
292
293         return status;
294 }
295
296 static bool epmapper_init_cb(void *ptr)
297 {
298         struct dcesrv_ep_context *ep_ctx =
299                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
300         uint16_t port;
301
302         port = _open_sockets(ep_ctx->ev_ctx,
303                              ep_ctx->msg_ctx,
304                              ndr_table_epmapper.syntax_id,
305                              135);
306         if (port == 135) {
307                 return true;
308         }
309
310         return false;
311 }
312
313 static bool epmapper_shutdown_cb(void *ptr)
314 {
315         srv_epmapper_cleanup();
316
317         return true;
318 }
319
320 static bool winreg_init_cb(void *ptr)
321 {
322         struct dcesrv_ep_context *ep_ctx =
323                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
324         struct ndr_syntax_id abstract_syntax = ndr_table_winreg.syntax_id;
325         const char *pipe_name = "winreg";
326         const char *rpcsrv_type;
327         uint16_t port;
328
329         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
330                                            "rpc_server",
331                                            "epmapper",
332                                            "none");
333
334         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
335             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
336                 NTSTATUS status;
337                 bool ok;
338
339                 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
340                                                  ep_ctx->msg_ctx,
341                                                  abstract_syntax,
342                                                  pipe_name);
343                 if (!ok) {
344                         return false;
345                 }
346                 port = _open_sockets(ep_ctx->ev_ctx,
347                                      ep_ctx->msg_ctx,
348                                      abstract_syntax,
349                                      0);
350                 if (port == 0) {
351                         return false;
352                 }
353
354                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
355                                                 ep_ctx->msg_ctx,
356                                                 &ndr_table_winreg,
357                                                 pipe_name,
358                                                 port);
359                 if (!NT_STATUS_IS_OK(status)) {
360                         return false;
361                 }
362         }
363
364         return true;
365 }
366
367 static bool winreg_shutdown_cb(void *ptr)
368 {
369         const char *rpcsrv_type;
370
371         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
372                                            "rpc_server",
373                                            "epmapper",
374                                            "none");
375
376         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
377             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
378                 NTSTATUS status;
379
380                 status = _rpc_ep_unregister(&ndr_table_winreg);
381                 if (!NT_STATUS_IS_OK(status)) {
382                         return false;
383                 }
384         }
385
386         return true;
387 }
388
389 static bool srvsvc_init_cb(void *ptr)
390 {
391         struct dcesrv_ep_context *ep_ctx =
392                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
393         struct ndr_syntax_id abstract_syntax = ndr_table_srvsvc.syntax_id;
394         const char *pipe_name = "srvsvc";
395         const char *rpcsrv_type;
396         uint16_t port;
397
398         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
399                                            "rpc_server",
400                                            "epmapper",
401                                            "none");
402
403         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
404             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
405                 NTSTATUS status;
406                 bool ok;
407
408                 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
409                                                  ep_ctx->msg_ctx,
410                                                  abstract_syntax,
411                                                  pipe_name);
412                 if (!ok) {
413                         return false;
414                 }
415
416                 port = _open_sockets(ep_ctx->ev_ctx,
417                                      ep_ctx->msg_ctx,
418                                      abstract_syntax,
419                                      0);
420                 if (port == 0) {
421                         return false;
422                 }
423
424                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
425                                           ep_ctx->msg_ctx,
426                                           &ndr_table_srvsvc,
427                                           pipe_name,
428                                           port);
429                 if (!NT_STATUS_IS_OK(status)) {
430                         return false;
431                 }
432         }
433
434         return true;
435 }
436
437 static bool srvsvc_shutdown_cb(void *ptr)
438 {
439         const char *rpcsrv_type;
440
441         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
442                                            "rpc_server",
443                                            "epmapper",
444                                            "none");
445
446         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
447             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
448                 NTSTATUS status;
449
450                 status =_rpc_ep_unregister(&ndr_table_srvsvc);
451                 if (!NT_STATUS_IS_OK(status)) {
452                         return false;
453                 }
454         }
455
456         return true;
457 }
458
459 static bool lsarpc_init_cb(void *ptr)
460 {
461         struct dcesrv_ep_context *ep_ctx =
462                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
463         struct ndr_syntax_id abstract_syntax = ndr_table_lsarpc.syntax_id;
464         const char *pipe_name = "lsarpc";
465         const char *rpcsrv_type;
466         uint16_t port;
467
468         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
469                                            "rpc_server",
470                                            "epmapper",
471                                            "none");
472
473         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
474             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
475                 NTSTATUS status;
476                 bool ok;
477
478                 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
479                                                  ep_ctx->msg_ctx,
480                                                  abstract_syntax,
481                                                  pipe_name);
482                 if (!ok) {
483                         return false;
484                 }
485
486                 port = _open_sockets(ep_ctx->ev_ctx,
487                                      ep_ctx->msg_ctx,
488                                      abstract_syntax,
489                                      0);
490                 if (port == 0) {
491                         return false;
492                 }
493
494                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
495                                           ep_ctx->msg_ctx,
496                                           &ndr_table_lsarpc,
497                                           pipe_name,
498                                           port);
499                 if (!NT_STATUS_IS_OK(status)) {
500                         return false;
501                 }
502         }
503
504         return true;
505 }
506
507 static bool lsarpc_shutdown_cb(void *ptr)
508 {
509         const char *rpcsrv_type;
510
511         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
512                                            "rpc_server",
513                                            "epmapper",
514                                            "none");
515
516         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
517             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
518                 NTSTATUS status;
519
520                 status = _rpc_ep_unregister(&ndr_table_lsarpc);
521                 if (!NT_STATUS_IS_OK(status)) {
522                         return false;
523                 }
524         }
525
526         return true;
527 }
528
529 static bool samr_init_cb(void *ptr)
530 {
531         struct dcesrv_ep_context *ep_ctx =
532                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
533         struct ndr_syntax_id abstract_syntax = ndr_table_samr.syntax_id;
534         const char *pipe_name = "samr";
535         const char *rpcsrv_type;
536         uint16_t port;
537
538         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
539                                            "rpc_server",
540                                            "epmapper",
541                                            "none");
542
543         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
544             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
545                 NTSTATUS status;
546                 bool ok;
547
548                 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
549                                                  ep_ctx->msg_ctx,
550                                                  abstract_syntax,
551                                                  pipe_name);
552                 if (!ok) {
553                         return false;
554                 }
555
556                 port = _open_sockets(ep_ctx->ev_ctx,
557                                      ep_ctx->msg_ctx,
558                                      abstract_syntax,
559                                      0);
560                 if (port == 0) {
561                         return false;
562                 }
563
564                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
565                                           ep_ctx->msg_ctx,
566                                           &ndr_table_samr,
567                                           pipe_name,
568                                           port);
569                 if (!NT_STATUS_IS_OK(status)) {
570                         return false;
571                 }
572         }
573
574         return true;
575 }
576
577 static bool samr_shutdown_cb(void *ptr)
578 {
579         const char *rpcsrv_type;
580
581         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
582                                            "rpc_server",
583                                            "epmapper",
584                                            "none");
585
586         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
587             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
588                 NTSTATUS status;
589
590                 status = _rpc_ep_unregister(&ndr_table_samr);
591                 if (!NT_STATUS_IS_OK(status)) {
592                         return false;
593                 }
594         }
595
596         return true;
597 }
598
599 static bool netlogon_init_cb(void *ptr)
600 {
601         struct dcesrv_ep_context *ep_ctx =
602                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
603         struct ndr_syntax_id abstract_syntax = ndr_table_netlogon.syntax_id;
604         const char *pipe_name = "netlogon";
605         const char *rpcsrv_type;
606         uint16_t port;
607
608         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
609                                            "rpc_server",
610                                            "epmapper",
611                                            "none");
612
613         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
614             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
615                 NTSTATUS status;
616                 bool ok;
617
618                 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
619                                                  ep_ctx->msg_ctx,
620                                                  abstract_syntax,
621                                                  pipe_name);
622                 if (!ok) {
623                         return false;
624                 }
625
626                 port = _open_sockets(ep_ctx->ev_ctx,
627                                      ep_ctx->msg_ctx,
628                                      abstract_syntax,
629                                      0);
630                 if (port == 0) {
631                         return false;
632                 }
633
634                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
635                                           ep_ctx->msg_ctx,
636                                           &ndr_table_netlogon,
637                                           pipe_name,
638                                           port);
639                 if (!NT_STATUS_IS_OK(status)) {
640                         return false;
641                 }
642         }
643
644         return true;
645 }
646
647 static bool netlogon_shutdown_cb(void *ptr)
648 {
649         const char *rpcsrv_type;
650
651         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
652                                            "rpc_server",
653                                            "epmapper",
654                                            "none");
655
656         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
657             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
658                 NTSTATUS status;
659
660                 status = _rpc_ep_unregister(&ndr_table_netlogon);
661                 if (!NT_STATUS_IS_OK(status)) {
662                         return false;
663                 }
664         }
665
666         return true;
667 }
668
669 static bool spoolss_init_cb(void *ptr)
670 {
671         struct dcesrv_ep_context *ep_ctx =
672                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
673         const char *rpcsrv_type;
674         bool ok;
675
676         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
677                                            "rpc_server",
678                                            "epmapper",
679                                            "none");
680
681         /*
682          * Migrate the printers first.
683          */
684         ok = nt_printing_tdb_migrate(ep_ctx->msg_ctx);
685         if (!ok) {
686                 return false;
687         }
688
689         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
690             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
691                 NTSTATUS status;
692
693                 status =rpc_ep_setup_register(ep_ctx->ev_ctx,
694                                          ep_ctx->msg_ctx,
695                                          &ndr_table_spoolss,
696                                          "spoolss",
697                                          0);
698                 if (!NT_STATUS_IS_OK(status)) {
699                         return false;
700                 }
701         }
702
703         return true;
704 }
705
706 static bool spoolss_shutdown_cb(void *ptr)
707 {
708         const char *rpcsrv_type;
709
710         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
711                                            "rpc_server",
712                                            "epmapper",
713                                            "none");
714
715         srv_spoolss_cleanup();
716
717         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
718             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
719                 NTSTATUS status;
720
721                 status = _rpc_ep_unregister(&ndr_table_spoolss);
722                 if (!NT_STATUS_IS_OK(status)) {
723                         return false;
724                 }
725         }
726
727         return true;
728 }
729
730 static bool svcctl_init_cb(void *ptr)
731 {
732         struct dcesrv_ep_context *ep_ctx =
733                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
734         const char *rpcsrv_type;
735         bool ok;
736
737         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
738                                            "rpc_server",
739                                            "epmapper",
740                                            "none");
741
742         ok = svcctl_init_winreg(ep_ctx->msg_ctx);
743         if (!ok) {
744                 return false;
745         }
746
747         /* initialize the control hooks */
748         init_service_op_table();
749
750         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
751             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
752                 NTSTATUS status;
753
754                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
755                                           ep_ctx->msg_ctx,
756                                           &ndr_table_svcctl,
757                                           "svcctl",
758                                           0);
759                 if (!NT_STATUS_IS_OK(status)) {
760                         return false;
761                 }
762         }
763
764         return true;
765 }
766
767 static bool svcctl_shutdown_cb(void *ptr)
768 {
769         const char *rpcsrv_type;
770
771         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
772                                            "rpc_server",
773                                            "epmapper",
774                                            "none");
775         shutdown_service_op_table();
776
777         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
778             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
779                 NTSTATUS status;
780
781                 status = _rpc_ep_unregister(&ndr_table_svcctl);
782                 if (!NT_STATUS_IS_OK(status)) {
783                         return false;
784                 }
785         }
786
787         return true;
788 }
789
790 static bool ntsvcs_init_cb(void *ptr)
791 {
792         struct dcesrv_ep_context *ep_ctx =
793                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
794         const char *rpcsrv_type;
795
796         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
797                                            "rpc_server",
798                                            "epmapper",
799                                            "none");
800
801         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
802             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
803                 NTSTATUS status;
804
805                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
806                                           ep_ctx->msg_ctx,
807                                           &ndr_table_ntsvcs,
808                                           "ntsvcs",
809                                           0);
810                 if (!NT_STATUS_IS_OK(status)) {
811                         return false;
812                 }
813         }
814
815         return true;
816 }
817
818 static bool ntsvcs_shutdown_cb(void *ptr)
819 {
820         const char *rpcsrv_type;
821
822         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
823                                            "rpc_server",
824                                            "epmapper",
825                                            "none");
826
827         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
828             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
829                 NTSTATUS status;
830
831                 status = _rpc_ep_unregister(&ndr_table_ntsvcs);
832                 if (!NT_STATUS_IS_OK(status)) {
833                         return false;
834                 }
835         }
836
837         return true;
838 }
839
840 static bool eventlog_init_cb(void *ptr)
841 {
842         struct dcesrv_ep_context *ep_ctx =
843                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
844         const char *rpcsrv_type;
845         bool ok;
846
847         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
848                                            "rpc_server",
849                                            "epmapper",
850                                            "none");
851
852         ok = eventlog_init_winreg(ep_ctx->msg_ctx);
853         if (!ok) {
854                 return false;
855         }
856
857         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
858             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
859                 NTSTATUS status;
860
861                 status =rpc_ep_setup_register(ep_ctx->ev_ctx,
862                                          ep_ctx->msg_ctx,
863                                          &ndr_table_eventlog,
864                                          "eventlog",
865                                          0);
866                 if (!NT_STATUS_IS_OK(status)) {
867                         return false;
868                 }
869         }
870
871         return true;
872 }
873
874 static bool eventlog_shutdown_cb(void *ptr)
875 {
876         const char *rpcsrv_type;
877
878         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
879                                            "rpc_server",
880                                            "epmapper",
881                                            "none");
882
883         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
884             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
885                 NTSTATUS status;
886
887                 status = _rpc_ep_unregister(&ndr_table_eventlog);
888                 if (!NT_STATUS_IS_OK(status)) {
889                         return false;
890                 }
891         }
892
893         return true;
894 }
895
896 static bool initshutdown_init_cb(void *ptr)
897 {
898         struct dcesrv_ep_context *ep_ctx =
899                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
900         const char *rpcsrv_type;
901
902         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
903                                            "rpc_server",
904                                            "epmapper",
905                                            "none");
906
907         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
908             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
909                 NTSTATUS status;
910
911                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
912                                           ep_ctx->msg_ctx,
913                                           &ndr_table_initshutdown,
914                                           "initshutdown",
915                                           0);
916                 if (!NT_STATUS_IS_OK(status)) {
917                         return false;
918                 }
919         }
920
921         return true;
922 }
923
924 static bool initshutdown_shutdown_cb(void *ptr)
925 {
926         const char *rpcsrv_type;
927
928         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
929                                            "rpc_server",
930                                            "epmapper",
931                                            "none");
932
933         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
934             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
935                 NTSTATUS status;
936
937                 status = _rpc_ep_unregister(&ndr_table_initshutdown);
938                 if (!NT_STATUS_IS_OK(status)) {
939                         return false;
940                 }
941         }
942
943         return true;
944 }
945
946 #ifdef DEVELOPER
947 static bool rpcecho_init_cb(void *ptr) {
948         struct dcesrv_ep_context *ep_ctx =
949                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
950         const char *rpcsrv_type;
951         uint16_t port;
952
953         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
954                                            "rpc_server",
955                                            "epmapper",
956                                            "none");
957
958         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
959             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
960                 NTSTATUS status;
961
962                 port = _open_sockets(ep_ctx->ev_ctx,
963                                      ep_ctx->msg_ctx,
964                                      ndr_table_rpcecho.syntax_id,
965                                      0);
966                 if (port == 0) {
967                         return false;
968                 }
969
970                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
971                                           ep_ctx->msg_ctx,
972                                           &ndr_table_rpcecho,
973                                           "rpcecho",
974                                           port);
975                 if (!NT_STATUS_IS_OK(status)) {
976                         return false;
977                 }
978         }
979
980         return true;
981 }
982
983 static bool rpcecho_shutdown_cb(void *ptr)
984 {
985         const char *rpcsrv_type;
986
987         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
988                                            "rpc_server",
989                                            "epmapper",
990                                            "none");
991
992         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
993             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
994                 NTSTATUS status;
995
996                 status = _rpc_ep_unregister(&ndr_table_rpcecho);
997                 if (!NT_STATUS_IS_OK(status)) {
998                         return false;
999                 }
1000         }
1001
1002         return true;
1003 }
1004 #endif
1005
1006 static bool netdfs_init_cb(void *ptr)
1007 {
1008         struct dcesrv_ep_context *ep_ctx =
1009                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
1010         struct ndr_syntax_id abstract_syntax = ndr_table_netdfs.syntax_id;
1011         const char *pipe_name = "netdfs";
1012         const char *rpcsrv_type;
1013         uint16_t port;
1014
1015         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
1016                                            "rpc_server",
1017                                            "epmapper",
1018                                            "none");
1019         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
1020             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
1021                 NTSTATUS status;
1022                 bool ok;
1023
1024                 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
1025                                                  ep_ctx->msg_ctx,
1026                                                  abstract_syntax,
1027                                                  pipe_name);
1028                 if (!ok) {
1029                         return false;
1030                 }
1031
1032                 port = _open_sockets(ep_ctx->ev_ctx,
1033                                      ep_ctx->msg_ctx,
1034                                      abstract_syntax,
1035                                      0);
1036                 if (port == 0) {
1037                         return false;
1038                 }
1039
1040                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
1041                                           ep_ctx->msg_ctx,
1042                                           &ndr_table_netdfs,
1043                                           pipe_name,
1044                                           port);
1045                 if (!NT_STATUS_IS_OK(status)) {
1046                         return false;
1047                 }
1048         }
1049
1050         return true;
1051 }
1052
1053 static bool netdfs_shutdown_cb(void *ptr) {
1054         const char *rpcsrv_type;
1055
1056         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
1057                                            "rpc_server",
1058                                            "epmapper",
1059                                            "none");
1060
1061         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
1062             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
1063                 NTSTATUS status;
1064
1065                 status = _rpc_ep_unregister(&ndr_table_netdfs);
1066                 if (!NT_STATUS_IS_OK(status)) {
1067                         return false;
1068                 }
1069         }
1070
1071         return true;
1072 }
1073
1074 static bool dssetup_init_cb(void *ptr)
1075 {
1076         struct dcesrv_ep_context *ep_ctx =
1077                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
1078         struct ndr_syntax_id abstract_syntax = ndr_table_dssetup.syntax_id;
1079         const char *pipe_name = "dssetup";
1080         const char *rpcsrv_type;
1081         uint16_t port;
1082
1083         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
1084                                            "rpc_server",
1085                                            "epmapper",
1086                                            "none");
1087
1088         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
1089             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
1090                 NTSTATUS status;
1091                 bool ok;
1092
1093                 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
1094                                                  ep_ctx->msg_ctx,
1095                                                  abstract_syntax,
1096                                                  pipe_name);
1097                 if (!ok) {
1098                         return false;
1099                 }
1100
1101                 port = _open_sockets(ep_ctx->ev_ctx,
1102                                      ep_ctx->msg_ctx,
1103                                      abstract_syntax,
1104                                      0);
1105                 if (port == 0) {
1106                         return false;
1107                 }
1108
1109                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
1110                                           ep_ctx->msg_ctx,
1111                                           &ndr_table_dssetup,
1112                                           "dssetup",
1113                                           port);
1114                 if (!NT_STATUS_IS_OK(status)) {
1115                         return false;
1116                 }
1117         }
1118
1119         return true;
1120 }
1121
1122 static bool dssetup_shutdown_cb(void *ptr) {
1123         const char *rpcsrv_type;
1124
1125         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
1126                                            "rpc_server",
1127                                            "epmapper",
1128                                            "none");
1129
1130         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
1131             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
1132                 NTSTATUS status;
1133
1134                 status = _rpc_ep_unregister(&ndr_table_dssetup);
1135                 if (!NT_STATUS_IS_OK(status)) {
1136                         return false;
1137                 }
1138         }
1139
1140         return true;
1141 }
1142
1143 static bool wkssvc_init_cb(void *ptr)
1144 {
1145         struct dcesrv_ep_context *ep_ctx =
1146                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
1147         struct ndr_syntax_id abstract_syntax = ndr_table_wkssvc.syntax_id;
1148         const char *pipe_name = "wkssvc";
1149         const char *rpcsrv_type;
1150         uint16_t port;
1151
1152         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
1153                                            "rpc_server",
1154                                            "epmapper",
1155                                            "none");
1156         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
1157             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
1158                 NTSTATUS status;
1159                 bool ok;
1160
1161                 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
1162                                                  ep_ctx->msg_ctx,
1163                                                  abstract_syntax,
1164                                                  pipe_name);
1165                 if (!ok) {
1166                         return false;
1167                 }
1168
1169                 port = _open_sockets(ep_ctx->ev_ctx,
1170                                      ep_ctx->msg_ctx,
1171                                      abstract_syntax,
1172                                      0);
1173                 if (port == 0) {
1174                         return false;
1175                 }
1176
1177                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
1178                                           ep_ctx->msg_ctx,
1179                                           &ndr_table_wkssvc,
1180                                           "wkssvc",
1181                                           port);
1182                 if (!NT_STATUS_IS_OK(status)) {
1183                         return false;
1184                 }
1185         }
1186
1187         return true;
1188 }
1189
1190 static bool wkssvc_shutdown_cb(void *ptr) {
1191         return NT_STATUS_IS_OK(_rpc_ep_unregister(&ndr_table_wkssvc));
1192 }
1193
1194 bool dcesrv_ep_setup(struct tevent_context *ev_ctx,
1195                      struct messaging_context *msg_ctx)
1196 {
1197         struct dcesrv_ep_context *ep_ctx;
1198
1199         struct rpc_srv_callbacks epmapper_cb;
1200
1201         struct rpc_srv_callbacks winreg_cb;
1202         struct rpc_srv_callbacks srvsvc_cb;
1203
1204         struct rpc_srv_callbacks lsarpc_cb;
1205         struct rpc_srv_callbacks samr_cb;
1206         struct rpc_srv_callbacks netlogon_cb;
1207
1208         struct rpc_srv_callbacks spoolss_cb;
1209         struct rpc_srv_callbacks svcctl_cb;
1210         struct rpc_srv_callbacks ntsvcs_cb;
1211         struct rpc_srv_callbacks eventlog_cb;
1212         struct rpc_srv_callbacks initshutdown_cb;
1213         struct rpc_srv_callbacks netdfs_cb;
1214 #ifdef DEVELOPER
1215         struct rpc_srv_callbacks rpcecho_cb;
1216 #endif
1217         struct rpc_srv_callbacks dssetup_cb;
1218         struct rpc_srv_callbacks wkssvc_cb;
1219
1220         const char *rpcsrv_type;
1221
1222         ep_ctx = talloc(ev_ctx, struct dcesrv_ep_context);
1223         if (ep_ctx == NULL) {
1224                 return false;
1225         }
1226
1227         ep_ctx->ev_ctx = ev_ctx;
1228         ep_ctx->msg_ctx = msg_ctx;
1229
1230         /* start endpoint mapper only if enabled */
1231         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
1232                                            "rpc_server",
1233                                            "epmapper",
1234                                            "none");
1235         if (StrCaseCmp(rpcsrv_type, "embedded") == 0) {
1236                 epmapper_cb.init         = epmapper_init_cb;
1237                 epmapper_cb.shutdown     = epmapper_shutdown_cb;
1238                 epmapper_cb.private_data = ep_ctx;
1239
1240                 if (!NT_STATUS_IS_OK(rpc_epmapper_init(&epmapper_cb))) {
1241                         return false;
1242                 }
1243         }
1244
1245         winreg_cb.init         = winreg_init_cb;
1246         winreg_cb.shutdown     = winreg_shutdown_cb;
1247         winreg_cb.private_data = ep_ctx;
1248         if (!NT_STATUS_IS_OK(rpc_winreg_init(&winreg_cb))) {
1249                 return false;
1250         }
1251
1252         srvsvc_cb.init         = srvsvc_init_cb;
1253         srvsvc_cb.shutdown     = srvsvc_shutdown_cb;
1254         srvsvc_cb.private_data = ep_ctx;
1255         if (!NT_STATUS_IS_OK(rpc_srvsvc_init(&srvsvc_cb))) {
1256                 return false;
1257         }
1258
1259
1260         lsarpc_cb.init         = lsarpc_init_cb;
1261         lsarpc_cb.shutdown     = lsarpc_shutdown_cb;
1262         lsarpc_cb.private_data = ep_ctx;
1263         if (!NT_STATUS_IS_OK(rpc_lsarpc_init(&lsarpc_cb))) {
1264                 return false;
1265         }
1266
1267         samr_cb.init         = samr_init_cb;
1268         samr_cb.shutdown     = samr_shutdown_cb;
1269         samr_cb.private_data = ep_ctx;
1270         if (!NT_STATUS_IS_OK(rpc_samr_init(&samr_cb))) {
1271                 return false;
1272         }
1273
1274         netlogon_cb.init         = netlogon_init_cb;
1275         netlogon_cb.shutdown     = netlogon_shutdown_cb;
1276         netlogon_cb.private_data = ep_ctx;
1277         if (!NT_STATUS_IS_OK(rpc_netlogon_init(&netlogon_cb))) {
1278                 return false;
1279         }
1280
1281         spoolss_cb.init         = spoolss_init_cb;
1282         spoolss_cb.shutdown     = spoolss_shutdown_cb;
1283         spoolss_cb.private_data = ep_ctx;
1284         if (!NT_STATUS_IS_OK(rpc_spoolss_init(&spoolss_cb))) {
1285                 return false;
1286         }
1287
1288
1289         svcctl_cb.init         = svcctl_init_cb;
1290         svcctl_cb.shutdown     = svcctl_shutdown_cb;
1291         svcctl_cb.private_data = ep_ctx;
1292         if (!NT_STATUS_IS_OK(rpc_svcctl_init(&svcctl_cb))) {
1293                 return false;
1294         }
1295
1296         ntsvcs_cb.init         = ntsvcs_init_cb;
1297         ntsvcs_cb.shutdown     = ntsvcs_shutdown_cb;
1298         ntsvcs_cb.private_data = ep_ctx;
1299         if (!NT_STATUS_IS_OK(rpc_ntsvcs_init(&ntsvcs_cb))) {
1300                 return false;
1301         }
1302
1303         eventlog_cb.init         = eventlog_init_cb;
1304         eventlog_cb.shutdown     = eventlog_shutdown_cb;
1305         eventlog_cb.private_data = ep_ctx;
1306         if (!NT_STATUS_IS_OK(rpc_eventlog_init(&eventlog_cb))) {
1307                 return false;
1308         }
1309
1310         initshutdown_cb.init         = initshutdown_init_cb;
1311         initshutdown_cb.shutdown     = initshutdown_shutdown_cb;
1312         initshutdown_cb.private_data = ep_ctx;
1313         if (!NT_STATUS_IS_OK(rpc_initshutdown_init(&initshutdown_cb))) {
1314                 return false;
1315         }
1316
1317         netdfs_cb.init         = netdfs_init_cb;
1318         netdfs_cb.shutdown     = netdfs_shutdown_cb;
1319         netdfs_cb.private_data = ep_ctx;
1320         if (!NT_STATUS_IS_OK(rpc_netdfs_init(&netdfs_cb))) {
1321                 return false;
1322         }
1323 #ifdef DEVELOPER
1324
1325         rpcecho_cb.init         = rpcecho_init_cb;
1326         rpcecho_cb.shutdown     = rpcecho_shutdown_cb;
1327         rpcecho_cb.private_data = ep_ctx;
1328         if (!NT_STATUS_IS_OK(rpc_rpcecho_init(&rpcecho_cb))) {
1329                 return false;
1330         }
1331 #endif
1332
1333         dssetup_cb.init         = dssetup_init_cb;
1334         dssetup_cb.shutdown     = dssetup_shutdown_cb;
1335         dssetup_cb.private_data = ep_ctx;
1336         if (!NT_STATUS_IS_OK(rpc_dssetup_init(&dssetup_cb))) {
1337                 return false;
1338         }
1339
1340         wkssvc_cb.init         = wkssvc_init_cb;
1341         wkssvc_cb.shutdown     = wkssvc_shutdown_cb;
1342         wkssvc_cb.private_data = ep_ctx;
1343         if (!NT_STATUS_IS_OK(rpc_wkssvc_init(&wkssvc_cb))) {
1344                 return false;
1345         }
1346
1347         return true;
1348 }
1349
1350 /* vim: set ts=8 sw=8 noet cindent ft=c.doxygen: */