2 Unix SMB/Netbios implementation.
4 Copyright (C) Simo Sorce 2010
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "smbd/smbd.h"
24 #include "include/printing.h"
25 #include "printing/nt_printing_migrate_internal.h"
27 #include "librpc/gen_ndr/srv_winreg.h"
28 #include "librpc/gen_ndr/srv_spoolss.h"
29 #include "rpc_server/rpc_server.h"
30 #include "rpc_server/rpc_ep_register.h"
31 #include "rpc_server/spoolss/srv_spoolss_nt.h"
32 #include "librpc/rpc/dcerpc_ep.h"
33 #include "lib/server_prefork.h"
35 #define SPOOLSS_PIPE_NAME "spoolss"
36 #define DAEMON_NAME "spoolssd"
38 #define SPOOLSS_MIN_CHILDREN 5
39 #define SPOOLSS_MAX_CHILDREN 25
40 #define SPOOLSS_SPAWN_RATE 5
41 #define SPOOLSS_MIN_LIFE 60 /* 1 minute minimum life time */
43 #define SPOOLSS_ALL_FINE 0x00
44 #define SPOOLSS_NEW_MAX 0x01
45 #define SPOLLSS_ENOSPC 0x02
47 static int spoolss_min_children;
48 static int spoolss_max_children;
49 static int spoolss_spawn_rate;
50 static int spoolss_prefork_status;
52 static void spoolss_prefork_config(void)
54 static int spoolss_prefork_config_init = false;
55 const char *prefork_str;
57 bool use_defaults = false;
60 if (!spoolss_prefork_config_init) {
61 spoolss_prefork_status = SPOOLSS_ALL_FINE;
62 spoolss_min_children = 0;
63 spoolss_max_children = 0;
64 spoolss_spawn_rate = 0;
65 spoolss_prefork_config_init = true;
68 prefork_str = lp_parm_const_string(GLOBAL_SECTION_SNUM,
69 "spoolssd", "prefork", "none");
70 if (strcmp(prefork_str, "none") == 0) {
73 ret = sscanf(prefork_str, "%d:%d:%d", &min, &max, &rate);
75 DEBUG(0, ("invalid format for spoolssd:prefork!\n"));
81 min = SPOOLSS_MIN_CHILDREN;
82 max = SPOOLSS_MAX_CHILDREN;
83 rate = SPOOLSS_SPAWN_RATE;
86 if (max > spoolss_max_children && spoolss_max_children != 0) {
87 spoolss_prefork_status |= SPOOLSS_NEW_MAX;
90 spoolss_min_children = min;
91 spoolss_max_children = max;
92 spoolss_spawn_rate = rate;
95 void start_spoolssd(struct tevent_context *ev_ctx,
96 struct messaging_context *msg_ctx);
98 static void spoolss_reopen_logs(void)
100 char *lfile = lp_logfile();
103 if (lfile == NULL || lfile[0] == '\0') {
104 rc = asprintf(&lfile, "%s/log.%s", get_dyn_LOGFILEBASE(), DAEMON_NAME);
106 lp_set_logfile(lfile);
110 if (strstr(lfile, DAEMON_NAME) == NULL) {
111 rc = asprintf(&lfile, "%s.%s", lp_logfile(), DAEMON_NAME);
113 lp_set_logfile(lfile);
122 static void update_conf(struct tevent_context *ev,
123 struct messaging_context *msg)
125 change_to_root_user();
126 lp_load(get_dyn_CONFIGFILE(), true, false, false, true);
127 reload_printers(ev, msg);
129 spoolss_reopen_logs();
130 spoolss_prefork_config();
133 static void smb_conf_updated(struct messaging_context *msg,
136 struct server_id server_id,
139 struct tevent_context *ev_ctx = talloc_get_type_abort(private_data,
140 struct tevent_context);
142 DEBUG(10, ("Got message saying smb.conf was updated. Reloading.\n"));
143 update_conf(ev_ctx, msg);
146 static void spoolss_sig_term_handler(struct tevent_context *ev,
147 struct tevent_signal *se,
153 exit_server_cleanly("termination signal");
156 static void spoolss_setup_sig_term_handler(struct tevent_context *ev_ctx)
158 struct tevent_signal *se;
160 se = tevent_add_signal(ev_ctx,
163 spoolss_sig_term_handler,
166 exit_server("failed to setup SIGTERM handler");
170 struct spoolss_hup_ctx {
171 struct messaging_context *msg_ctx;
172 struct prefork_pool *pfp;
175 static void spoolss_sig_hup_handler(struct tevent_context *ev,
176 struct tevent_signal *se,
182 struct spoolss_hup_ctx *hup_ctx;
184 hup_ctx = talloc_get_type_abort(pvt, struct spoolss_hup_ctx);
186 DEBUG(1,("Reloading printers after SIGHUP\n"));
187 update_conf(ev, hup_ctx->msg_ctx);
189 /* relay to all children */
190 prefork_send_signal_to_all(hup_ctx->pfp, SIGHUP);
193 static void spoolss_setup_sig_hup_handler(struct tevent_context *ev_ctx,
194 struct prefork_pool *pfp,
195 struct messaging_context *msg_ctx)
197 struct spoolss_hup_ctx *hup_ctx;
198 struct tevent_signal *se;
200 hup_ctx = talloc(ev_ctx, struct spoolss_hup_ctx);
202 exit_server("failed to setup SIGHUP handler");
205 hup_ctx->msg_ctx = msg_ctx;
207 se = tevent_add_signal(ev_ctx,
210 spoolss_sig_hup_handler,
213 exit_server("failed to setup SIGHUP handler");
217 static bool spoolss_init_cb(void *ptr)
219 struct messaging_context *msg_ctx = talloc_get_type_abort(
220 ptr, struct messaging_context);
222 return nt_printing_tdb_migrate(msg_ctx);
225 static bool spoolss_shutdown_cb(void *ptr)
227 srv_spoolss_cleanup();
234 struct spoolss_chld_sig_hup_ctx {
235 struct messaging_context *msg_ctx;
236 struct pf_worker_data *pf;
239 static void spoolss_chld_sig_hup_handler(struct tevent_context *ev,
240 struct tevent_signal *se,
246 struct spoolss_chld_sig_hup_ctx *shc;
248 shc = talloc_get_type_abort(pvt, struct spoolss_chld_sig_hup_ctx);
250 /* avoid wasting CPU cycles if we are going to exit soon anyways */
251 if (shc->pf != NULL &&
252 shc->pf->cmds == PF_SRV_MSG_EXIT) {
256 change_to_root_user();
257 DEBUG(1,("Reloading printers after SIGHUP\n"));
258 reload_printers(ev, shc->msg_ctx);
259 spoolss_reopen_logs();
262 static bool spoolss_setup_chld_hup_handler(struct tevent_context *ev_ctx,
263 struct pf_worker_data *pf,
264 struct messaging_context *msg_ctx)
266 struct spoolss_chld_sig_hup_ctx *shc;
267 struct tevent_signal *se;
269 shc = talloc(ev_ctx, struct spoolss_chld_sig_hup_ctx);
271 DEBUG(1, ("failed to setup SIGHUP handler"));
275 shc->msg_ctx = msg_ctx;
277 se = tevent_add_signal(ev_ctx,
280 spoolss_chld_sig_hup_handler,
283 DEBUG(1, ("failed to setup SIGHUP handler"));
290 static bool spoolss_child_init(struct tevent_context *ev_ctx,
291 struct pf_worker_data *pf)
294 struct rpc_srv_callbacks spoolss_cb;
295 struct messaging_context *msg_ctx = server_messaging_context();
298 status = reinit_after_fork(msg_ctx, ev_ctx,
299 procid_self(), true);
300 if (!NT_STATUS_IS_OK(status)) {
301 DEBUG(0,("reinit_after_fork() failed\n"));
302 smb_panic("reinit_after_fork() failed");
305 spoolss_reopen_logs();
307 ok = spoolss_setup_chld_hup_handler(ev_ctx, pf, msg_ctx);
312 if (!serverid_register(procid_self(), FLAG_MSG_GENERAL)) {
316 if (!locking_init()) {
320 messaging_register(msg_ctx, ev_ctx,
321 MSG_SMB_CONF_UPDATED, smb_conf_updated);
323 /* try to reinit rpc queues */
324 spoolss_cb.init = spoolss_init_cb;
325 spoolss_cb.shutdown = spoolss_shutdown_cb;
326 spoolss_cb.private_data = msg_ctx;
328 status = rpc_winreg_init(NULL);
329 if (!NT_STATUS_IS_OK(status)) {
330 DEBUG(0, ("Failed to register winreg rpc inteface! (%s)\n",
335 status = rpc_spoolss_init(&spoolss_cb);
336 if (!NT_STATUS_IS_OK(status)) {
337 DEBUG(0, ("Failed to register spoolss rpc inteface! (%s)\n",
342 reload_printers(ev_ctx, msg_ctx);
347 struct spoolss_children_data {
348 struct tevent_context *ev_ctx;
349 struct messaging_context *msg_ctx;
350 struct pf_worker_data *pf;
358 static void spoolss_next_client(void *pvt);
360 static int spoolss_children_main(struct tevent_context *ev_ctx,
361 struct pf_worker_data *pf,
367 struct messaging_context *msg_ctx = server_messaging_context();
368 struct spoolss_children_data *data;
372 ok = spoolss_child_init(ev_ctx, pf);
377 data = talloc(ev_ctx, struct spoolss_children_data);
382 data->ev_ctx = ev_ctx;
383 data->msg_ctx = msg_ctx;
384 data->lock_fd = lock_fd;
385 data->listen_fd_size = listen_fd_size;
386 data->listen_fds = listen_fds;
387 data->listening = false;
389 /* loop until it is time to exit */
390 while (pf->status != PF_WORKER_EXITING) {
391 /* try to see if it is time to schedule the next client */
392 spoolss_next_client(data);
394 ret = tevent_loop_once(ev_ctx);
396 DEBUG(0, ("tevent_loop_once() exited with %d: %s\n",
397 ret, strerror(errno)));
398 pf->status = PF_WORKER_EXITING;
405 static void spoolss_client_terminated(void *pvt)
407 struct spoolss_children_data *data;
409 data = talloc_get_type_abort(pvt, struct spoolss_children_data);
411 if (data->pf->num_clients) {
412 data->pf->num_clients--;
414 DEBUG(2, ("Invalid num clients, aborting!\n"));
415 data->pf->status = PF_WORKER_EXITING;
419 spoolss_next_client(pvt);
422 struct spoolss_new_client {
423 struct spoolss_children_data *data;
424 struct sockaddr_un sunaddr;
428 static void spoolss_handle_client(struct tevent_req *req);
430 static void spoolss_next_client(void *pvt)
432 struct tevent_req *req;
433 struct spoolss_children_data *data;
434 struct spoolss_new_client *next;
436 data = talloc_get_type_abort(pvt, struct spoolss_children_data);
438 if (data->pf->num_clients == 0) {
439 data->pf->status = PF_WORKER_IDLE;
442 if (data->pf->cmds == PF_SRV_MSG_EXIT) {
443 DEBUG(2, ("Parent process commands we terminate!\n"));
447 if (data->listening ||
448 data->pf->num_clients >= data->pf->allowed_clients) {
449 /* nothing to do for now we are already listening
450 * or reached the number of clients we are allowed
451 * to handle in parallel */
455 next = talloc_zero(data, struct spoolss_new_client);
457 DEBUG(1, ("Out of memory!?\n"));
461 next->addrlen = sizeof(next->sunaddr);
463 req = prefork_listen_send(next, data->ev_ctx, data->pf,
464 data->listen_fd_size,
467 (struct sockaddr *)&next->sunaddr,
470 DEBUG(1, ("Failed to make listening request!?\n"));
474 tevent_req_set_callback(req, spoolss_handle_client, next);
476 data->listening = true;
479 static void spoolss_handle_client(struct tevent_req *req)
481 struct spoolss_children_data *data;
482 struct spoolss_new_client *client;
486 client = tevent_req_callback_data(req, struct spoolss_new_client);
489 ret = prefork_listen_recv(req, &sd);
491 /* this will free the request too */
493 /* we are done listening */
494 data->listening = false;
497 DEBUG(1, ("Failed to accept client connection!\n"));
498 /* bail out if we are not serving any other client */
499 if (data->pf->num_clients == 0) {
500 data->pf->status = PF_WORKER_EXITING;
506 DEBUG(1, ("Server asks us to die!\n"));
507 data->pf->status = PF_WORKER_EXITING;
511 DEBUG(2, ("Spoolss preforked child %d got client connection!\n",
512 (int)(data->pf->pid)));
514 named_pipe_accept_function(data->ev_ctx, data->msg_ctx,
515 SPOOLSS_PIPE_NAME, sd,
516 spoolss_client_terminated, data);
519 /* ==== Main Process Functions ==== */
521 static void spoolssd_sig_chld_handler(struct tevent_context *ev_ctx,
522 struct tevent_signal *se,
523 int signum, int count,
524 void *siginfo, void *pvt)
526 struct prefork_pool *pfp;
530 pfp = talloc_get_type_abort(pvt, struct prefork_pool);
532 /* run the cleanup function to make sure all dead children are
533 * properly and timely retired. */
534 prefork_cleanup_loop(pfp);
536 /* now check we do not descend below the minimum */
537 active = prefork_count_active_children(pfp, &total);
540 if (total < spoolss_min_children) {
541 n = total - spoolss_min_children;
542 } else if (total - active < (total / 4)) {
543 n = spoolss_min_children;
547 r = prefork_add_children(ev_ctx, pfp, n);
549 DEBUG(10, ("Tried to start %d children but only,"
550 "%d were actually started.!\n", n, r));
557 static bool spoolssd_setup_sig_chld_handler(struct tevent_context *ev_ctx,
558 struct prefork_pool *pfp)
560 struct tevent_signal *se;
562 se = tevent_add_signal(ev_ctx, ev_ctx, SIGCHLD, 0,
563 spoolssd_sig_chld_handler, pfp);
565 DEBUG(0, ("Failed to setup SIGCHLD handler!\n"));
572 static bool spoolssd_schedule_check(struct tevent_context *ev_ctx,
573 struct prefork_pool *pfp,
574 struct timeval current_time);
575 static void spoolssd_check_children(struct tevent_context *ev_ctx,
576 struct tevent_timer *te,
577 struct timeval current_time,
580 static bool spoolssd_setup_children_monitor(struct tevent_context *ev_ctx,
581 struct prefork_pool *pfp)
585 ok = spoolssd_setup_sig_chld_handler(ev_ctx, pfp);
590 ok = spoolssd_schedule_check(ev_ctx, pfp, tevent_timeval_current());
594 static bool spoolssd_schedule_check(struct tevent_context *ev_ctx,
595 struct prefork_pool *pfp,
596 struct timeval current_time)
598 struct tevent_timer *te;
599 struct timeval next_event;
601 /* check situation again in 10 seconds */
602 next_event = tevent_timeval_current_ofs(10, 0);
604 /* check when the socket becomes readable, so that children
605 * are checked only when there is some activity */
606 te = tevent_add_timer(ev_ctx, pfp, next_event,
607 spoolssd_check_children, pfp);
609 DEBUG(2, ("Failed to set up children monitoring!\n"));
616 static void spoolssd_check_children(struct tevent_context *ev_ctx,
617 struct tevent_timer *te,
618 struct timeval current_time,
621 struct prefork_pool *pfp;
625 pfp = talloc_get_type_abort(pvt, struct prefork_pool);
627 if ((spoolss_prefork_status & SPOOLSS_NEW_MAX) &&
628 !(spoolss_prefork_status & SPOLLSS_ENOSPC)) {
629 ret = prefork_expand_pool(pfp, spoolss_max_children);
631 spoolss_prefork_status |= SPOLLSS_ENOSPC;
633 spoolss_prefork_status &= ~SPOOLSS_NEW_MAX;
636 active = prefork_count_active_children(pfp, &total);
638 if (total - active < spoolss_spawn_rate) {
639 n = prefork_add_children(ev_ctx, pfp, spoolss_spawn_rate);
640 if (n < spoolss_spawn_rate) {
641 DEBUG(10, ("Tried to start 5 children but only,"
642 "%d were actually started.!\n", n));
646 if (total - active > spoolss_min_children) {
647 if ((total - spoolss_min_children) >= spoolss_spawn_rate) {
648 prefork_retire_children(pfp, spoolss_spawn_rate,
649 time(NULL) - SPOOLSS_MIN_LIFE);
653 ret = spoolssd_schedule_check(ev_ctx, pfp, current_time);
656 void start_spoolssd(struct tevent_context *ev_ctx,
657 struct messaging_context *msg_ctx)
659 struct prefork_pool *pool;
660 struct rpc_srv_callbacks spoolss_cb;
661 struct dcerpc_binding_vector *v;
669 DEBUG(1, ("Forking SPOOLSS Daemon\n"));
674 DEBUG(0, ("Failed to fork SPOOLSS [%s], aborting ...\n",
685 close_low_fds(false);
687 status = reinit_after_fork(msg_ctx,
689 procid_self(), true);
690 if (!NT_STATUS_IS_OK(status)) {
691 DEBUG(0,("reinit_after_fork() failed\n"));
692 smb_panic("reinit_after_fork() failed");
695 spoolss_reopen_logs();
696 spoolss_prefork_config();
698 /* the listening fd must be created before the children are actually
700 listen_fd = create_named_pipe_socket(SPOOLSS_PIPE_NAME);
701 if (listen_fd == -1) {
705 ret = listen(listen_fd, spoolss_max_children);
707 DEBUG(0, ("Failed to listen on spoolss pipe - %s\n",
713 /* start children before any more initialization is done */
714 ok = prefork_create_pool(ev_ctx, ev_ctx, 1, &listen_fd,
715 spoolss_min_children,
716 spoolss_max_children,
717 &spoolss_children_main, NULL,
720 spoolss_setup_sig_term_handler(ev_ctx);
721 spoolss_setup_sig_hup_handler(ev_ctx, pool, msg_ctx);
723 if (!serverid_register(procid_self(),
724 FLAG_MSG_GENERAL|FLAG_MSG_SMBD
725 |FLAG_MSG_PRINT_GENERAL)) {
729 if (!locking_init()) {
733 messaging_register(msg_ctx, NULL,
734 MSG_PRINTER_UPDATE, print_queue_receive);
735 messaging_register(msg_ctx, ev_ctx,
736 MSG_SMB_CONF_UPDATED, smb_conf_updated);
738 mem_ctx = talloc_new(NULL);
739 if (mem_ctx == NULL) {
744 * Initialize spoolss with an init function to convert printers first.
745 * static_init_rpc will try to initialize the spoolss server too but you
746 * can't register it twice.
748 spoolss_cb.init = spoolss_init_cb;
749 spoolss_cb.shutdown = spoolss_shutdown_cb;
750 spoolss_cb.private_data = msg_ctx;
752 status = rpc_winreg_init(NULL);
753 if (!NT_STATUS_IS_OK(status)) {
754 DEBUG(0, ("Failed to register winreg rpc inteface! (%s)\n",
759 status = rpc_spoolss_init(&spoolss_cb);
760 if (!NT_STATUS_IS_OK(status)) {
761 DEBUG(0, ("Failed to register spoolss rpc inteface! (%s)\n",
766 status = dcerpc_binding_vector_new(mem_ctx, &v);
767 if (!NT_STATUS_IS_OK(status)) {
768 DEBUG(0, ("Failed to create binding vector (%s)\n",
773 status = dcerpc_binding_vector_add_np_default(&ndr_table_spoolss, v);
774 if (!NT_STATUS_IS_OK(status)) {
775 DEBUG(0, ("Failed to add np to binding vector (%s)\n",
780 status = rpc_ep_register(ev_ctx, msg_ctx, &ndr_table_spoolss, v);
781 if (!NT_STATUS_IS_OK(status)) {
782 DEBUG(0, ("Failed to register spoolss endpoint! (%s)\n",
787 talloc_free(mem_ctx);
789 ok = spoolssd_setup_children_monitor(ev_ctx, pool);
791 DEBUG(0, ("Failed to setup children monitoring!\n"));
795 reload_printers(ev_ctx, msg_ctx);
797 DEBUG(1, ("SPOOLSS Daemon Started (%d)\n", getpid()));
800 ret = tevent_loop_wait(ev_ctx);
802 /* should not be reached */
803 DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
804 ret, (ret == 0) ? "out of events" : strerror(errno)));