From e5a951325a6cac8567af3a66de6d2df577508ae4 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Wed, 10 Oct 2007 15:34:30 -0500 Subject: [GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch. (This used to be commit 5c6c8e1fe93f340005110a7833946191659d88ab) --- source3/smbd/server.c | 246 +++++++++++++++++++++++++++++++------------------- 1 file changed, 155 insertions(+), 91 deletions(-) (limited to 'source3/smbd/server.c') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 72eeb7ee6a..0f47a550e9 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4,7 +4,6 @@ Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Martin Pool 2002 Copyright (C) Jelmer Vernooij 2002-2003 - Copyright (C) James Peach 2007 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -293,34 +292,26 @@ static BOOL allowable_number_of_smbd_processes(void) return num_children < max_processes; } -/**************************************************************************** - Are we idle enough that we could safely exit? -****************************************************************************/ - -static BOOL smbd_is_idle(void) -{ - /* Currently we define "idle" as having no client connections. */ - return count_all_current_connections() == 0; -} - /**************************************************************************** Open the socket communication. ****************************************************************************/ -static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ports) +static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ports) { + int num_interfaces = iface_count(); int num_sockets = 0; int fd_listenset[FD_SETSIZE]; fd_set listen_set; int s; int maxfd = 0; int i; - struct timeval idle_timeout = timeval_zero(); + char *ports; - if (server_mode == SERVER_MODE_INETD) { + if (!is_daemon) { return open_sockets_inetd(); } + #ifdef HAVE_ATEXIT { static int atexit_set; @@ -333,21 +324,116 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ /* Stop zombies */ CatchSignal(SIGCLD, sig_cld); - + FD_ZERO(&listen_set); - /* At this point, it doesn't matter what daemon mode we are in, we - * need some sockets to listen on. - */ - num_sockets = smbd_sockinit(smb_ports, fd_listenset, &idle_timeout); - if (num_sockets == 0) { - return False; + /* use a reasonable default set of ports - listing on 445 and 139 */ + if (!smb_ports) { + ports = lp_smb_ports(); + if (!ports || !*ports) { + ports = smb_xstrdup(SMB_PORTS); + } else { + ports = smb_xstrdup(ports); + } + } else { + ports = smb_xstrdup(smb_ports); } - for (i = 0; i < num_sockets; ++i) { - FD_SET(fd_listenset[i], &listen_set); - maxfd = MAX(maxfd, fd_listenset[i]); - } + if (lp_interfaces() && lp_bind_interfaces_only()) { + /* We have been given an interfaces line, and been + told to only bind to those interfaces. Create a + socket per interface and bind to only these. + */ + + /* Now open a listen socket for each of the + interfaces. */ + for(i = 0; i < num_interfaces; i++) { + struct in_addr *ifip = iface_n_ip(i); + fstring tok; + const char *ptr; + + if(ifip == NULL) { + DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address !\n", i)); + continue; + } + + for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { + unsigned port = atoi(tok); + if (port == 0 || port > 0xffff) { + continue; + } + s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); + if(s == -1) + return False; + + /* ready to listen */ + set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,user_socket_options); + + /* Set server socket to non-blocking for the accept. */ + set_blocking(s,False); + + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { + DEBUG(0,("listen: %s\n",strerror(errno))); + close(s); + return False; + } + FD_SET(s,&listen_set); + maxfd = MAX( maxfd, s); + + num_sockets++; + if (num_sockets >= FD_SETSIZE) { + DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); + return False; + } + } + } + } else { + /* Just bind to 0.0.0.0 - accept connections + from anywhere. */ + + fstring tok; + const char *ptr; + + num_interfaces = 1; + + for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { + unsigned port = atoi(tok); + if (port == 0 || port > 0xffff) continue; + /* open an incoming socket */ + s = open_socket_in(SOCK_STREAM, port, 0, + interpret_addr(lp_socket_address()),True); + if (s == -1) + return(False); + + /* ready to listen */ + set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,user_socket_options); + + /* Set server socket to non-blocking for the accept. */ + set_blocking(s,False); + + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { + DEBUG(0,("open_sockets_smbd: listen: %s\n", + strerror(errno))); + close(s); + return False; + } + + fd_listenset[num_sockets] = s; + FD_SET(s,&listen_set); + maxfd = MAX( maxfd, s); + + num_sockets++; + + if (num_sockets >= FD_SETSIZE) { + DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); + return False; + } + } + } + + SAFE_FREE(ports); /* Setup the main smbd so that we can get messages. Note that @@ -380,7 +466,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ for each incoming connection */ DEBUG(2,("waiting for a connection\n")); while (1) { - struct timeval now; + struct timeval now, idle_timeout; fd_set r_fds, w_fds; int num; @@ -396,6 +482,8 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ } } + idle_timeout = timeval_zero(); + memcpy((char *)&r_fds, (char *)&listen_set, sizeof(listen_set)); FD_ZERO(&w_fds); @@ -405,21 +493,9 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ &r_fds, &w_fds, &idle_timeout, &maxfd); - if (timeval_is_zero(&idle_timeout)) { - num = sys_select(maxfd + 1, &r_fds, &w_fds, - NULL, NULL); - } else { - num = sys_select(maxfd + 1, &r_fds, &w_fds, - NULL, &idle_timeout); - - /* If the idle timeout fired and we are idle, exit - * gracefully. We expect to be running under a process - * controller that will restart us if necessry. - */ - if (num == 0 && smbd_is_idle()) { - exit_server_cleanly("idle timeout"); - } - } + num = sys_select(maxfd+1,&r_fds,&w_fds,NULL, + timeval_is_zero(&idle_timeout) ? + NULL : &idle_timeout); if (num == -1 && errno == EINTR) { if (got_sig_term) { @@ -436,7 +512,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ continue; } - + if (run_events(smbd_event_context(), num, &r_fds, &w_fds)) { continue; } @@ -476,13 +552,8 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ /* Ensure child is set to blocking mode */ set_blocking(smbd_server_fd(),True); - /* In interactive mode, return with a connected socket. - * Foreground and daemon modes should fork worker - * processes. - */ - if (server_mode == SERVER_MODE_INTERACTIVE) { + if (smbd_server_fd() != -1 && interactive) return True; - } if (allowable_number_of_smbd_processes() && smbd_server_fd() != -1 && @@ -694,8 +765,6 @@ static void exit_server_common(enum server_exit_reason how, locking_end(); printing_end(); - server_encryption_shutdown(); - if (how != SERVER_EXIT_NORMAL) { int oldlevel = DEBUGLEVEL; @@ -804,26 +873,23 @@ extern void build_options(BOOL screen); int main(int argc,const char *argv[]) { /* shall I run as a daemon */ - BOOL no_process_group = False; - BOOL log_stdout = False; - const char *ports = NULL; - const char *profile_level = NULL; + static BOOL is_daemon = False; + static BOOL interactive = False; + static BOOL Fork = True; + static BOOL no_process_group = False; + static BOOL log_stdout = False; + static char *ports = NULL; + static char *profile_level = NULL; int opt; poptContext pc; BOOL print_build_options = False; - enum smb_server_mode server_mode = SERVER_MODE_DAEMON; - struct poptOption long_options[] = { POPT_AUTOHELP - {"daemon", 'D', POPT_ARG_VAL, &server_mode, SERVER_MODE_DAEMON, - "Become a daemon (default)" }, - {"interactive", 'i', POPT_ARG_VAL, &server_mode, SERVER_MODE_INTERACTIVE, - "Run interactive (not a daemon)"}, - {"foreground", 'F', POPT_ARG_VAL, &server_mode, SERVER_MODE_FOREGROUND, - "Run daemon in foreground (for daemontools, etc.)" }, - {"no-process-group", '\0', POPT_ARG_VAL, &no_process_group, True, - "Don't create a new process group" }, + {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" }, + {"interactive", 'i', POPT_ARG_VAL, &interactive, True, "Run interactive (not a daemon)"}, + {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools, etc.)" }, + {"no-process-group", '\0', POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" }, {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, {"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" }, {"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"}, @@ -870,14 +936,16 @@ extern void build_options(BOOL screen); set_remote_machine_name("smbd", False); - if (server_mode == SERVER_MODE_INTERACTIVE) { + if (interactive) { + Fork = False; log_stdout = True; - if (DEBUGLEVEL >= 9) { - talloc_enable_leak_report(); - } } - if (log_stdout && server_mode == SERVER_MODE_DAEMON) { + if (interactive && (DEBUGLEVEL >= 9)) { + talloc_enable_leak_report(); + } + + if (log_stdout && Fork) { DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); exit(1); } @@ -967,19 +1035,21 @@ extern void build_options(BOOL screen); DEBUG(3,( "loaded services\n")); - if (is_a_socket(0)) { - if (server_mode == SERVER_MODE_DAEMON) { - DEBUG(0,("standard input is a socket, " - "assuming -F option\n")); - } - server_mode = SERVER_MODE_INETD; + if (!is_daemon && !is_a_socket(0)) { + if (!interactive) + DEBUG(0,("standard input is not a socket, assuming -D option\n")); + + /* + * Setting is_daemon here prevents us from eventually calling + * the open_sockets_inetd() + */ + + is_daemon = True; } - if (server_mode == SERVER_MODE_DAEMON) { + if (is_daemon && !interactive) { DEBUG( 3, ( "Becoming a daemon.\n" ) ); - become_daemon(True, no_process_group); - } else if (server_mode == SERVER_MODE_FOREGROUND) { - become_daemon(False, no_process_group); + become_daemon(Fork, no_process_group); } #if HAVE_SETPGID @@ -987,18 +1057,15 @@ extern void build_options(BOOL screen); * If we're interactive we want to set our own process group for * signal management. */ - if (server_mode == SERVER_MODE_INTERACTIVE && !no_process_group) { + if (interactive && !no_process_group) setpgid( (pid_t)0, (pid_t)0); - } #endif if (!directory_exist(lp_lockdir(), NULL)) mkdir(lp_lockdir(), 0755); - if (server_mode != SERVER_MODE_INETD && - server_mode != SERVER_MODE_INTERACTIVE) { + if (is_daemon) pidfile_create("smbd"); - } /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */ @@ -1052,10 +1119,9 @@ extern void build_options(BOOL screen); running as a daemon -- bad things will happen if smbd is launched via inetd and we fork a copy of ourselves here */ - if (server_mode != SERVER_MODE_INETD && - server_mode != SERVER_MODE_INTERACTIVE) { + + if ( is_daemon && !interactive ) start_background_queue(); - } /* Always attempt to initialize DMAPI. We will only use it later if * lp_dmapi_support is set on the share, but we need a single global @@ -1063,9 +1129,8 @@ extern void build_options(BOOL screen); */ dmapi_init_session(); - if (!open_sockets_smbd(server_mode, ports)) { + if (!open_sockets_smbd(is_daemon, interactive, ports)) exit(1); - } /* * everything after this point is run after the fork() @@ -1078,8 +1143,7 @@ extern void build_options(BOOL screen); /* Possibly reload the services file. Only worth doing in * daemon mode. In inetd mode, we know we only just loaded this. */ - if (server_mode != SERVER_MODE_INETD && - server_mode != SERVER_MODE_INTERACTIVE) { + if (is_daemon) { reload_services(True); } -- cgit