Beispiel #1
0
/*
 * If we detect that stdio cannot handle file descriptors above 255, this
 * functions tries to reassign 'fd' to a file descriptor above 255 in order to
 * reserve lower file descriptors for stdio. File descriptors below 3 or above
 * 255 are returned as-is. The original file descriptor is closed if it was
 * reassigned. On systems which do not need this workaround, the original
 * file descriptor is returned.
 *
 * @note The FD_CLOEXEC flag set will be cleared on the new file descriptor if
 *		 the file descriptor is successfully reassigned.
 *
 * @return	On success a new file descriptor above 255 is returned.
 *         	On failure or if reassigning was not necessary the original file
 *			descriptor is returned.
 */
int
fd_get_non_stdio(int fd)
{
	if (fd_need_non_stdio() && fd > 2 && fd < 256) {
		int nfd, saved_errno;

		saved_errno = errno;
		nfd = fcntl(fd, F_DUPFD, 256);
		if (nfd > 0) {
			close(fd);
			compat_socket_duped(fd, nfd);
			fd = nfd;
		}
		errno = saved_errno;
	}

	/*
	 * On Windows, files and sockets do not share the same ID space.
	 * Therefore, on that platform we use this routine as a hook to
	 * record active socket descriptors in a table.
	 *		--RAM, 2015-04-05
	 */

	if (is_running_on_mingw()) {
		/* We don't expect thread race conditions here */
		if G_UNLIKELY(NULL == fd_sockets)
			fd_sockets = hset_create(HASH_KEY_SELF, 0);

		if (is_a_socket(fd))
			hset_insert(fd_sockets, int_to_pointer(fd));
	}

	return fd;
}
Beispiel #2
0
/**
 * Mark a file descriptor as being preserved from closing by
 * fd_close_unpreserved_from().
 */
void
fd_preserve(int fd)
{
	g_assert(!is_a_socket(fd));

	ONCE_FLAG_RUN(fd_preserved_allocated, fd_preserved_allocate);
	hset_insert(fd_preserved, int_to_pointer(fd));
}
Beispiel #3
0
/**
 * Errors during startup (e.g. bad options) need to be reported somewhere,
 * although we have not yet parsed the options to work out where the user
 * wants them.
 *
 * In inetd mode, we can't write to stderr because that will corrupt the
 * stream, so if it looks like stderr is a socket we go to syslog instead.
 **/
static int dcc_setup_startup_log(void)
{
    rs_trace_set_level(RS_LOG_INFO);
    if (!is_a_socket(STDERR_FILENO)) {
        rs_add_logger(rs_logger_file, RS_LOG_DEBUG, 0, STDERR_FILENO);
    } else {
        openlog("distccd", LOG_PID, LOG_DAEMON);
        rs_add_logger(rs_logger_syslog, RS_LOG_DEBUG, NULL, 0);
    }

    return 0;
}
int daemon_main(void)
{
	extern char *config_file;
	extern int orig_umask;
	char *pid_file;

	if (is_a_socket(STDIN_FILENO)) {
		int i;

		/* we are running via inetd - close off stdout and
		   stderr so that library functions (and getopt) don't
		   try to use them. Redirect them to /dev/null */
		for (i=1;i<3;i++) {
			close(i); 
			open("/dev/null", O_RDWR);
		}

		set_nonblocking(STDIN_FILENO);

		return start_daemon(STDIN_FILENO);
	}

	become_daemon();

	if (!lp_load(config_file, 1)) {
		fprintf(stderr,"failed to load config file %s\n", config_file);
		exit_cleanup(RERR_SYNTAX);
	}

	log_open();

	rprintf(FINFO,"rsyncd version %s starting\n",VERSION);

	if (((pid_file = lp_pid_file()) != NULL) && (*pid_file != '\0')) {
		char pidbuf[16];
		int fd;
		int pid = (int) getpid();
		cleanup_set_pid(pid);
		if ((fd = do_open(lp_pid_file(), O_WRONLY|O_CREAT|O_TRUNC,
					0666 & ~orig_umask)) == -1) {
		    cleanup_set_pid(0);
		    fprintf(stderr,"failed to create pid file %s\n", pid_file);
		    exit_cleanup(RERR_FILEIO);
		}
		slprintf(pidbuf, sizeof(pidbuf), "%d\n", pid);
		write(fd, pidbuf, strlen(pidbuf));
		close(fd);
	}

	start_accept_loop(rsync_port, start_daemon);
	return -1;
}
Beispiel #5
0
/**
 * Close all open sockets and files, allowing a (somewhat) graceful
 * shutdown() of socket connections.  This eliminates the abortive
 * TCP RST sent by a Winsock-based system when the close() occurs.
 **/
void close_all(void)
{
#ifdef SHUTDOWN_ALL_SOCKETS
	int max_fd;
	int fd;
	int ret;
	STRUCT_STAT st;

	max_fd = sysconf(_SC_OPEN_MAX) - 1;
	for (fd = max_fd; fd >= 0; fd--) {
		if ((ret = do_fstat(fd, &st)) == 0) {
			if (is_a_socket(fd))
				ret = shutdown(fd, 2);
			ret = close(fd);
		}
	}
#endif
}
Beispiel #6
0
static int dcc_should_be_inetd(void)
{
    /* Work out if we ought to serve stdin or be a standalone daemon */
    if (opt_inetd_mode)
        return 1;
    else if (opt_daemon_mode)
        return 0;
    else if (is_a_socket(STDIN_FILENO)) {
        rs_log_info("stdin is socket; assuming --inetd mode");
        return 1;
    } else if (isatty(STDIN_FILENO)) {
        rs_log_info("stdin is a tty; assuming --daemon mode");
        return 0;
    } else {
        rs_log_info("stdin is neither a tty nor a socket; assuming --daemon mode");
        return 0;
    }
}
static inline int
emulate_poll_with_select(struct pollfd *fds, unsigned int n, int timeout)
{
	struct timeval tv;
	unsigned i;
	fd_set rfds, wfds, efds;
	int ret, max_fd = -1;

	FD_ZERO(&rfds);
	FD_ZERO(&wfds);
	FD_ZERO(&efds);

	for (i = 0; i < n; i++) {
		int fd = cast_to_fd(fds[i].fd);

		safety_assert(!is_valid_fd(fd) || is_a_socket(fd) || is_a_fifo(fd));

		if (!is_okay_for_select(fd) || i >= FD_SETSIZE) {
			fds[i].revents = POLLERR;
			continue;
		}

		max_fd = MAX(fd, max_fd);
		fds[i].revents = 0;

		if (POLLIN & fds[i].events) {
			FD_SET(socket_fd(fd), &rfds);
		}
		if (POLLOUT & fds[i].events) {
			FD_SET(socket_fd(fd), &wfds);
		}
		FD_SET(socket_fd(fd), &efds);
	}

	if (timeout >= 0) {
		tv.tv_sec = timeout / 1000;
		tv.tv_usec = (timeout % 1000) * 1000UL;
	}

	ret = select(max_fd + 1, &rfds, &wfds, &efds, timeout < 0 ? NULL : &tv);

	if (ret > 0) {

		n = MIN(n, FD_SETSIZE);	/* POLLERR is already set above */
		for (i = 0; i < n; i++) {
			int fd = cast_to_fd(fds[i].fd);

			if (!is_okay_for_select(fd))
				continue;

			if (FD_ISSET(fd, &rfds)) {
				fds[i].revents |= POLLIN;
			}
			if (FD_ISSET(fd, &wfds)) {
				fds[i].revents |= POLLOUT;
			}
			if (FD_ISSET(fd, &efds)) {
				fds[i].revents |= POLLERR;
			}
		}
	} else if (ret < 0) {
		s_warning("error during select(): %m");
	}
	return ret;
}
Beispiel #8
0
 int main(int argc,const char *argv[])
{
	/* shall I run as a daemon */
	bool is_daemon = false;
	bool interactive = false;
	bool Fork = true;
	bool no_process_group = false;
	bool log_stdout = false;
	char *ports = NULL;
	char *profile_level = NULL;
	int opt;
	poptContext pc;
	bool print_build_options = False;
        enum {
		OPT_DAEMON = 1000,
		OPT_INTERACTIVE,
		OPT_FORK,
		OPT_NO_PROCESS_GROUP,
		OPT_LOG_STDOUT
	};
	struct poptOption long_options[] = {
	POPT_AUTOHELP
	{"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
	{"interactive", 'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE, "Run interactive (not a daemon)"},
	{"foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Run daemon in foreground (for daemontools, etc.)" },
	{"no-process-group", '\0', POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
	{"log-stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "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"},
	{"profiling-level", 'P', POPT_ARG_STRING, &profile_level, 0, "Set profiling level","PROFILE_LEVEL"},
	POPT_COMMON_SAMBA
	POPT_COMMON_DYNCONFIG
	POPT_TABLEEND
	};
	struct smbd_parent_context *parent = NULL;
	TALLOC_CTX *frame;
	NTSTATUS status;
	uint64_t unique_id;
	struct tevent_context *ev_ctx;
	struct messaging_context *msg_ctx;

	/*
	 * Do this before any other talloc operation
	 */
	talloc_enable_null_tracking();
	frame = talloc_stackframe();

	setup_logging(argv[0], DEBUG_DEFAULT_STDOUT);

	load_case_tables();

	smbd_init_globals();

	TimeInit();

#ifdef HAVE_SET_AUTH_PARAMETERS
	set_auth_parameters(argc,argv);
#endif

	pc = poptGetContext("smbd", argc, argv, long_options, 0);
	while((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt)  {
		case OPT_DAEMON:
			is_daemon = true;
			break;
		case OPT_INTERACTIVE:
			interactive = true;
			break;
		case OPT_FORK:
			Fork = false;
			break;
		case OPT_NO_PROCESS_GROUP:
			no_process_group = true;
			break;
		case OPT_LOG_STDOUT:
			log_stdout = true;
			break;
		case 'b':
			print_build_options = True;
			break;
		default:
			d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
				  poptBadOption(pc, 0), poptStrerror(opt));
			poptPrintUsage(pc, stderr, 0);
			exit(1);
		}
	}
	poptFreeContext(pc);

	if (interactive) {
		Fork = False;
		log_stdout = True;
	}

	if (log_stdout) {
		setup_logging(argv[0], DEBUG_STDOUT);
	} else {
		setup_logging(argv[0], DEBUG_FILE);
	}

	if (print_build_options) {
		build_options(True); /* Display output to screen as well as debug */
		exit(0);
	}

#ifdef HAVE_SETLUID
	/* needed for SecureWare on SCO */
	setluid(0);
#endif

	set_remote_machine_name("smbd", False);

	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);
	}

	/* we want to re-seed early to prevent time delays causing
           client problems at a later date. (tridge) */
	generate_random_buffer(NULL, 0);

	/* get initial effective uid and gid */
	sec_init();

	/* make absolutely sure we run as root - to handle cases where people
	   are crazy enough to have it setuid */
	gain_root_privilege();
	gain_root_group_privilege();

	fault_setup();
	dump_core_setup("smbd", lp_logfile());

	/* we are never interested in SIGPIPE */
	BlockSignals(True,SIGPIPE);

#if defined(SIGFPE)
	/* we are never interested in SIGFPE */
	BlockSignals(True,SIGFPE);
#endif

#if defined(SIGUSR2)
	/* We are no longer interested in USR2 */
	BlockSignals(True,SIGUSR2);
#endif

	/* POSIX demands that signals are inherited. If the invoking process has
	 * these signals masked, we will have problems, as we won't recieve them. */
	BlockSignals(False, SIGHUP);
	BlockSignals(False, SIGUSR1);
	BlockSignals(False, SIGTERM);

	/* Ensure we leave no zombies until we
	 * correctly set up child handling below. */

	CatchChild();

	/* we want total control over the permissions on created files,
	   so set our umask to 0 */
	umask(0);

	reopen_logs();

	DEBUG(0,("smbd version %s started.\n", samba_version_string()));
	DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));

	DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
		 (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid()));

	/* Output the build options to the debug log */ 
	build_options(False);

	if (sizeof(uint16) < 2 || sizeof(uint32) < 4) {
		DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
		exit(1);
	}

	if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
		DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
		exit(1);
	}

	/* Init the security context and global current_user */
	init_sec_ctx();

	/*
	 * Initialize the event context. The event context needs to be
	 * initialized before the messaging context, cause the messaging
	 * context holds an event context.
	 * FIXME: This should be s3_tevent_context_init()
	 */
	ev_ctx = server_event_context();
	if (ev_ctx == NULL) {
		exit(1);
	}

	/*
	 * Init the messaging context
	 * FIXME: This should only call messaging_init()
	 */
	msg_ctx = server_messaging_context();
	if (msg_ctx == NULL) {
		exit(1);
	}

	/*
	 * Reloading of the printers will not work here as we don't have a
	 * server info and rpc services set up. It will be called later.
	 */
	if (!reload_services(NULL, -1, False)) {
		exit(1);
	}

	/* ...NOTE... Log files are working from this point! */

	DEBUG(3,("loaded services\n"));

	init_structs();

#ifdef WITH_PROFILE
	if (!profile_setup(msg_ctx, False)) {
		DEBUG(0,("ERROR: failed to setup profiling\n"));
		return -1;
	}
	if (profile_level != NULL) {
		int pl = atoi(profile_level);
		struct server_id src;

		DEBUG(1, ("setting profiling level: %s\n",profile_level));
		src.pid = getpid();
		set_profile_level(pl, src);
	}
#endif

	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 (is_daemon && !interactive) {
		DEBUG( 3, ( "Becoming a daemon.\n" ) );
		become_daemon(Fork, no_process_group, log_stdout);
	}

        generate_random_buffer((uint8_t *)&unique_id, sizeof(unique_id));
        set_my_unique_id(unique_id);

#if HAVE_SETPGID
	/*
	 * If we're interactive we want to set our own process group for
	 * signal management.
	 */
	if (interactive && !no_process_group)
		setpgid( (pid_t)0, (pid_t)0);
#endif

	if (!directory_exist(lp_lockdir()))
		mkdir(lp_lockdir(), 0755);

	if (is_daemon)
		pidfile_create("smbd");

	status = reinit_after_fork(msg_ctx,
				   ev_ctx,
				   procid_self(), false);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("reinit_after_fork() failed\n"));
		exit(1);
	}

	smbd_server_conn->msg_ctx = msg_ctx;

	smbd_setup_sig_term_handler();
	smbd_setup_sig_hup_handler(ev_ctx,
				   msg_ctx);

	/* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */

	if (smbd_memcache() == NULL) {
		exit(1);
	}

	memcache_set_global(smbd_memcache());

	/* Initialise the password backed before the global_sam_sid
	   to ensure that we fetch from ldap before we make a domain sid up */

	if(!initialize_password_db(false, ev_ctx))
		exit(1);

	if (!secrets_init()) {
		DEBUG(0, ("ERROR: smbd can not open secrets.tdb\n"));
		exit(1);
	}

	if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) {
		struct loadparm_context *lp_ctx = loadparm_init_s3(NULL, loadparm_s3_context());
		if (!open_schannel_session_store(NULL, lp_ctx)) {
			DEBUG(0,("ERROR: Samba cannot open schannel store for secured NETLOGON operations.\n"));
			exit(1);
		}
		TALLOC_FREE(lp_ctx);
	}

	if(!get_global_sam_sid()) {
		DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n"));
		exit(1);
	}

	if (!sessionid_init()) {
		exit(1);
	}

	if (!connections_init(True))
		exit(1);

	if (!locking_init())
		exit(1);

	if (!messaging_tdb_parent_init(ev_ctx)) {
		exit(1);
	}

	if (!notify_internal_parent_init(ev_ctx)) {
		exit(1);
	}

	if (!serverid_parent_init(ev_ctx)) {
		exit(1);
	}

	if (!W_ERROR_IS_OK(registry_init_full()))
		exit(1);

	/* Open the share_info.tdb here, so we don't have to open
	   after the fork on every single connection.  This is a small
	   performance improvment and reduces the total number of system
	   fds used. */
	if (!share_info_db_init()) {
		DEBUG(0,("ERROR: failed to load share info db.\n"));
		exit(1);
	}

	status = init_system_info();
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("ERROR: failed to setup system user info: %s.\n",
			  nt_errstr(status)));
		return -1;
	}

	if (!init_guest_info()) {
		DEBUG(0,("ERROR: failed to setup guest info.\n"));
		return -1;
	}

	if (!file_init(smbd_server_conn)) {
		DEBUG(0, ("ERROR: file_init failed\n"));
		return -1;
	}

	/* This MUST be done before start_epmd() because otherwise
	 * start_epmd() forks and races against dcesrv_ep_setup() to
	 * call directory_create_or_exist() */
	if (!directory_create_or_exist(lp_ncalrpc_dir(), geteuid(), 0755)) {
		DEBUG(0, ("Failed to create pipe directory %s - %s\n",
			  lp_ncalrpc_dir(), strerror(errno)));
		return -1;
	}

	if (is_daemon && !interactive) {
		if (rpc_epmapper_daemon() == RPC_DAEMON_FORK) {
			start_epmd(ev_ctx, msg_ctx);
		}
	}

	if (!dcesrv_ep_setup(ev_ctx, msg_ctx)) {
		exit(1);
	}

	/* only start other daemons if we are running as a daemon
	 * -- bad things will happen if smbd is launched via inetd
	 *  and we fork a copy of ourselves here */
	if (is_daemon && !interactive) {

		if (rpc_lsasd_daemon() == RPC_DAEMON_FORK) {
			start_lsasd(ev_ctx, msg_ctx);
		}

		if (!_lp_disable_spoolss() &&
		    (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) {
			bool bgq = lp_parm_bool(-1, "smbd", "backgroundqueue", true);

			if (!printing_subsystem_init(ev_ctx, msg_ctx, true, bgq)) {
				exit(1);
			}
		}
	} else if (!_lp_disable_spoolss() &&
		   (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) {
		if (!printing_subsystem_init(ev_ctx, msg_ctx, false, false)) {
			exit(1);
		}
	}

	if (!is_daemon) {
		/* inetd mode */
		TALLOC_FREE(frame);

		/* Started from inetd. fd 0 is the socket. */
		/* We will abort gracefully when the client or remote system
		   goes away */
		smbd_server_conn->sock = dup(0);

		/* close our standard file descriptors */
		if (!debug_get_output_is_stdout()) {
			close_low_fds(False); /* Don't close stderr */
		}

#ifdef HAVE_ATEXIT
		atexit(killkids);
#endif

	        /* Stop zombies */
		smbd_setup_sig_chld_handler(ev_ctx);

		smbd_process(ev_ctx, smbd_server_conn);

		exit_server_cleanly(NULL);
		return(0);
	}

	parent = talloc_zero(ev_ctx, struct smbd_parent_context);
	if (!parent) {
		exit_server("talloc(struct smbd_parent_context) failed");
	}
	parent->interactive = interactive;

	if (!open_sockets_smbd(parent, ev_ctx, msg_ctx, ports))
		exit_server("open_sockets_smbd() failed");

	/* do a printer update now that all messaging has been set up,
	 * before we allow clients to start connecting */
	printing_subsystem_update(ev_ctx, msg_ctx, false);

	TALLOC_FREE(frame);
	/* make sure we always have a valid stackframe */
	frame = talloc_stackframe();

	smbd_parent_loop(ev_ctx, parent);

	exit_server_cleanly(NULL);
	TALLOC_FREE(frame);
	return(0);
}
Beispiel #9
0
 int main(int argc, const char *argv[])
{
	static bool is_daemon;
	static bool opt_interactive;
	static bool Fork = true;
	static bool no_process_group;
	static bool log_stdout;
	poptContext pc;
	char *p_lmhosts = NULL;
	int opt;
	enum {
		OPT_DAEMON = 1000,
		OPT_INTERACTIVE,
		OPT_FORK,
		OPT_NO_PROCESS_GROUP,
		OPT_LOG_STDOUT
	};
	struct poptOption long_options[] = {
	POPT_AUTOHELP
	{"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon(default)" },
	{"interactive", 'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE, "Run interactive (not a daemon)" },
	{"foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Run daemon in foreground (for daemontools & etc)" },
	{"no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
	{"log-stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
	{"hosts", 'H', POPT_ARG_STRING, &p_lmhosts, 0, "Load a netbios hosts file"},
	{"port", 'p', POPT_ARG_INT, &global_nmb_port, 0, "Listen on the specified port" },
	POPT_COMMON_SAMBA
	{ NULL }
	};
	TALLOC_CTX *frame;
	NTSTATUS status;

	/*
	 * Do this before any other talloc operation
	 */
	talloc_enable_null_tracking();
	frame = talloc_stackframe();

	setup_logging(argv[0], DEBUG_DEFAULT_STDOUT);

	load_case_tables();

	global_nmb_port = NMB_PORT;

	pc = poptGetContext("nmbd", argc, argv, long_options, 0);
	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		case OPT_DAEMON:
			is_daemon = true;
			break;
		case OPT_INTERACTIVE:
			opt_interactive = true;
			break;
		case OPT_FORK:
			Fork = false;
			break;
		case OPT_NO_PROCESS_GROUP:
			no_process_group = true;
			break;
		case OPT_LOG_STDOUT:
			log_stdout = true;
			break;
		default:
			d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
				  poptBadOption(pc, 0), poptStrerror(opt));
			poptPrintUsage(pc, stderr, 0);
			exit(1);
		}
	};
	poptFreeContext(pc);

	global_in_nmbd = true;
	
	StartupTime = time(NULL);
	
	sys_srandom(time(NULL) ^ sys_getpid());
	
	if (!override_logfile) {
		char *lfile = NULL;
		if (asprintf(&lfile, "%s/log.nmbd", get_dyn_LOGFILEBASE()) < 0) {
			exit(1);
		}
		lp_set_logfile(lfile);
		SAFE_FREE(lfile);
	}
	
	fault_setup();
	dump_core_setup("nmbd", lp_logfile());
	
	/* POSIX demands that signals are inherited. If the invoking process has
	 * these signals masked, we will have problems, as we won't receive them. */
	BlockSignals(False, SIGHUP);
	BlockSignals(False, SIGUSR1);
	BlockSignals(False, SIGTERM);

#if defined(SIGFPE)
	/* we are never interested in SIGFPE */
	BlockSignals(True,SIGFPE);
#endif

	/* We no longer use USR2... */
#if defined(SIGUSR2)
	BlockSignals(True, SIGUSR2);
#endif

	if ( opt_interactive ) {
		Fork = False;
		log_stdout = True;
	}

	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);
	}

	if (log_stdout) {
		setup_logging(argv[0], DEBUG_STDOUT);
	} else {
		setup_logging( argv[0], DEBUG_FILE);
	}

	reopen_logs();

	DEBUG(0,("nmbd version %s started.\n", samba_version_string()));
	DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));

	if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
		DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
		exit(1);
	}

	if (nmbd_messaging_context() == NULL) {
		return 1;
	}

	if ( !reload_nmbd_services(False) )
		return(-1);

	if(!init_names())
		return -1;

	reload_nmbd_services( True );

	if (strequal(lp_workgroup(),"*")) {
		DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
		exit(1);
	}

	set_samba_nb_type();

	if (!is_daemon && !is_a_socket(0)) {
		DEBUG(0,("standard input is not a socket, assuming -D option\n"));
		is_daemon = True;
	}
  
	if (is_daemon && !opt_interactive) {
		DEBUG( 2, ( "Becoming a daemon.\n" ) );
		become_daemon(Fork, no_process_group, log_stdout);
	}

#if HAVE_SETPGID
	/*
	 * If we're interactive we want to set our own process group for 
	 * signal management.
	 */
	if (opt_interactive && !no_process_group)
		setpgid( (pid_t)0, (pid_t)0 );
#endif

	if (nmbd_messaging_context() == NULL) {
		return 1;
	}

#ifndef SYNC_DNS
	/* Setup the async dns. We do it here so it doesn't have all the other
		stuff initialised and thus chewing memory and sockets */
	if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
		start_async_dns();
	}
#endif

	if (!directory_exist(lp_lockdir())) {
		mkdir(lp_lockdir(), 0755);
	}

	pidfile_create("nmbd");

	status = reinit_after_fork(nmbd_messaging_context(),
				   nmbd_event_context(),
				   procid_self(), false);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("reinit_after_fork() failed\n"));
		exit(1);
	}

	if (!nmbd_setup_sig_term_handler())
		exit(1);
	if (!nmbd_setup_sig_hup_handler())
		exit(1);

	/* get broadcast messages */

	if (!serverid_register(procid_self(),
				FLAG_MSG_GENERAL |
				FLAG_MSG_NMBD |
				FLAG_MSG_DBWRAP)) {
		DEBUG(1, ("Could not register myself in serverid.tdb\n"));
		exit(1);
	}

	messaging_register(nmbd_messaging_context(), NULL,
			   MSG_FORCE_ELECTION, nmbd_message_election);
#if 0
	/* Until winsrepl is done. */
	messaging_register(nmbd_messaging_context(), NULL,
			   MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
#endif
	messaging_register(nmbd_messaging_context(), NULL,
			   MSG_SHUTDOWN, nmbd_terminate);
	messaging_register(nmbd_messaging_context(), NULL,
			   MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services);
	messaging_register(nmbd_messaging_context(), NULL,
			   MSG_SEND_PACKET, msg_nmbd_send_packet);

	TimeInit();

	DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );

	if ( !open_sockets( is_daemon, global_nmb_port ) ) {
		kill_async_dns_child();
		return 1;
	}

	/* Determine all the IP addresses we have. */
	load_interfaces();

	/* Create an nmbd subnet record for each of the above. */
	if( False == create_subnets() ) {
		DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
		kill_async_dns_child();
		exit(1);
	}

	/* Load in any static local names. */ 
	if (p_lmhosts) {
		set_dyn_LMHOSTSFILE(p_lmhosts);
	}
	load_lmhosts_file(get_dyn_LMHOSTSFILE());
	DEBUG(3,("Loaded hosts file %s\n", get_dyn_LMHOSTSFILE()));

	/* If we are acting as a WINS server, initialise data structures. */
	if( !initialise_wins() ) {
		DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
		kill_async_dns_child();
		exit(1);
	}

	/* 
	 * Register nmbd primary workgroup and nmbd names on all
	 * the broadcast subnets, and on the WINS server (if specified).
	 * Also initiate the startup of our primary workgroup (start
	 * elections if we are setup as being able to be a local
	 * master browser.
	 */

	if( False == register_my_workgroup_and_names() ) {
		DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
		kill_async_dns_child();
		exit(1);
	}

	if (!initialize_nmbd_proxy_logon()) {
		DEBUG(0,("ERROR: Failed setup nmbd_proxy_logon.\n"));
		kill_async_dns_child();
		exit(1);
	}

	if (!nmbd_init_packet_server()) {
		kill_async_dns_child();
                exit(1);
        }

	TALLOC_FREE(frame);
	process();

	kill_async_dns_child();
	return(0);
}
Beispiel #10
0
/**************************************************************************** **
 main program
 **************************************************************************** */
 int main(int argc, const char *argv[])
{
	pstring logfile;
	static BOOL opt_interactive;
	poptContext pc;
	static char *p_lmhosts = dyn_LMHOSTSFILE;
	static BOOL no_process_group = False;
	struct poptOption long_options[] = {
	POPT_AUTOHELP
	{"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon(default)" },
	{"interactive", 'i', POPT_ARG_VAL, &opt_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" },
	{"hosts", 'H', POPT_ARG_STRING, &p_lmhosts, 'H', "Load a netbios hosts file"},
	{"port", 'p', POPT_ARG_INT, &global_nmb_port, NMB_PORT, "Listen on the specified port" },
	POPT_COMMON_SAMBA
	{ NULL }
	};

	load_case_tables();

	global_nmb_port = NMB_PORT;

	pc = poptGetContext("nmbd", argc, argv, long_options, 0);
	while (poptGetNextOpt(pc) != -1) {};
	poptFreeContext(pc);

	global_in_nmbd = True;
	
	StartupTime = time(NULL);
	
	sys_srandom(time(NULL) ^ sys_getpid());
	
	if (!override_logfile) {
		slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE);
		lp_set_logfile(logfile);
	}
	
	fault_setup((void (*)(void *))fault_continue );
	dump_core_setup("nmbd");
	
	/* POSIX demands that signals are inherited. If the invoking process has
	 * these signals masked, we will have problems, as we won't receive them. */
	BlockSignals(False, SIGHUP);
	BlockSignals(False, SIGUSR1);
	BlockSignals(False, SIGTERM);
	
	CatchSignal( SIGHUP,  SIGNAL_CAST sig_hup );
	CatchSignal( SIGTERM, SIGNAL_CAST sig_term );
	
#if defined(SIGFPE)
	/* we are never interested in SIGFPE */
	BlockSignals(True,SIGFPE);
#endif

	/* We no longer use USR2... */
#if defined(SIGUSR2)
	BlockSignals(True, SIGUSR2);
#endif

	if ( opt_interactive ) {
		Fork = False;
		log_stdout = True;
	}

	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);
	}

	setup_logging( argv[0], log_stdout );

	reopen_logs();

	DEBUG( 0, ( "Netbios nameserver version %s started.\n", SAMBA_VERSION_STRING) );
	DEBUGADD( 0, ( "%s\n", COPYRIGHT_STARTUP_MESSAGE ) );

	if ( !reload_nmbd_services(False) )
		return(-1);

	if(!init_names())
		return -1;

	reload_nmbd_services( True );

	if (strequal(lp_workgroup(),"*")) {
		DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
		exit(1);
	}

	set_samba_nb_type();

	if (!is_daemon && !is_a_socket(0)) {
		DEBUG(0,("standard input is not a socket, assuming -D option\n"));
		is_daemon = True;
	}
  
	if (is_daemon && !opt_interactive) {
		DEBUG( 2, ( "Becoming a daemon.\n" ) );
		become_daemon(Fork, no_process_group);
	}

#if HAVE_SETPGID
	/*
	 * If we're interactive we want to set our own process group for 
	 * signal management.
	 */
	if (opt_interactive && !no_process_group)
		setpgid( (pid_t)0, (pid_t)0 );
#endif

#ifndef SYNC_DNS
	/* Setup the async dns. We do it here so it doesn't have all the other
		stuff initialised and thus chewing memory and sockets */
	if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
		start_async_dns();
	}
#endif

	if (!directory_exist(lp_lockdir(), NULL)) {
		mkdir(lp_lockdir(), 0755);
	}

	pidfile_create("nmbd");
	message_init();
	message_register(MSG_FORCE_ELECTION, nmbd_message_election, NULL);
#if 0
	/* Until winsrepl is done. */
	message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry, NULL);
#endif
	message_register(MSG_SHUTDOWN, nmbd_terminate, NULL);
	message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services, NULL);
	message_register(MSG_SEND_PACKET, msg_nmbd_send_packet, NULL);

	TimeInit();

	DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );

	if ( !open_sockets( is_daemon, global_nmb_port ) ) {
		kill_async_dns_child();
		return 1;
	}

	/* Determine all the IP addresses we have. */
	load_interfaces();

	/* Create an nmbd subnet record for each of the above. */
	if( False == create_subnets() ) {
		DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
		kill_async_dns_child();
		exit(1);
	}

	/* Load in any static local names. */ 
	load_lmhosts_file(p_lmhosts);
	DEBUG(3,("Loaded hosts file %s\n", p_lmhosts));

	/* If we are acting as a WINS server, initialise data structures. */
	if( !initialise_wins() ) {
		DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
		kill_async_dns_child();
		exit(1);
	}

	/* 
	 * Register nmbd primary workgroup and nmbd names on all
	 * the broadcast subnets, and on the WINS server (if specified).
	 * Also initiate the startup of our primary workgroup (start
	 * elections if we are setup as being able to be a local
	 * master browser.
	 */

	if( False == register_my_workgroup_and_names() ) {
		DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
		kill_async_dns_child();
		exit(1);
	}

	/* We can only take signals in the select. */
	BlockSignals( True, SIGTERM );

	process();

	if (dbf)
		x_fclose(dbf);
	kill_async_dns_child();
	return(0);
}
Beispiel #11
0
static inline bool
fd_is_opened(const int fd)
{
	return is_open_fd(fd) || is_a_socket(fd) || is_a_fifo(fd);
}
Beispiel #12
0
 int main2(int argc,const char *argv[])
{
	/* shall I run as a daemon */
	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;
	int opt;
#ifndef _XBOX
	poptContext pc;

	struct poptOption long_options[] = {
	POPT_AUTOHELP
	{"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"},
	POPT_COMMON_SAMBA
	POPT_COMMON_DYNCONFIG
	POPT_TABLEEND
	};
#else
	interactive = True;
	log_stdout = True;
#endif

	load_case_tables();

#ifdef HAVE_SET_AUTH_PARAMETERS
	set_auth_parameters(argc,argv);
#endif

#ifndef _XBOX
	pc = poptGetContext("smbd", argc, argv, long_options, 0);
	
	while((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt)  {
		case 'b':
			build_options(True); /* Display output to screen as well as debug */ 
			exit(0);
			break;
		}
	}

	poptFreeContext(pc);
#endif

#ifdef HAVE_SETLUID
	/* needed for SecureWare on SCO */
	setluid(0);
#endif

	sec_init();

	set_remote_machine_name("smbd", False);

	if (interactive) {
		Fork = False;
		log_stdout = True;
	}

	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);
	}

	setup_logging(argv[0],log_stdout);

	/* we want to re-seed early to prevent time delays causing
           client problems at a later date. (tridge) */
	generate_random_buffer(NULL, 0);

	/* make absolutely sure we run as root - to handle cases where people
	   are crazy enough to have it setuid */

	gain_root_privilege();
	gain_root_group_privilege();

#ifndef _XBOX
	fault_setup((void (*)(void *))exit_server_fault);
	dump_core_setup("smbd");
#endif

	CatchSignal(SIGTERM , SIGNAL_CAST sig_term);
#ifndef _XBOX
	CatchSignal(SIGHUP,SIGNAL_CAST sig_hup);
	
	/* we are never interested in SIGPIPE */
	BlockSignals(True,SIGPIPE);
#endif

#if defined(SIGFPE)
	/* we are never interested in SIGFPE */
	BlockSignals(True,SIGFPE);
#endif

#if defined(SIGUSR2)
	/* We are no longer interested in USR2 */
	BlockSignals(True,SIGUSR2);
#endif

	/* POSIX demands that signals are inherited. If the invoking process has
	 * these signals masked, we will have problems, as we won't recieve them. */
#ifndef _XBOX
	BlockSignals(False, SIGHUP);
#endif
	BlockSignals(False, SIGUSR1);
	BlockSignals(False, SIGTERM);

	/* we want total control over the permissions on created files,
	   so set our umask to 0 */
	umask(0);

	init_sec_ctx();

	reopen_logs();

	DEBUG(0,( "smbd version %s started.\n", SAMBA_VERSION_STRING));
	DEBUGADD( 0, ( "%s\n", COPYRIGHT_STARTUP_MESSAGE ) );

	DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
		 (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid()));

	/* Output the build options to the debug log */ 
	build_options(False);

	if (sizeof(uint16) < 2 || sizeof(uint32) < 4) {
		DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
		exit(1);
	}

	/*
	 * Do this before reload_services.
	 */

	if (!reload_services(False))
		return(-1);	

	init_structs();

#ifdef WITH_PROFILE
	if (!profile_setup(False)) {
		DEBUG(0,("ERROR: failed to setup profiling\n"));
		return -1;
	}
#endif

	DEBUG(3,( "loaded services\n"));

	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 (is_daemon && !interactive) {
		DEBUG( 3, ( "Becoming a daemon.\n" ) );
		become_daemon(Fork, no_process_group);
	}

#if HAVE_SETPGID
	/*
	 * If we're interactive we want to set our own process group for
	 * signal management.
	 */
	if (interactive && !no_process_group)
		setpgid( (pid_t)0, (pid_t)0);
#endif

	if (!directory_exist(lp_lockdir(), NULL))
		mkdir(lp_lockdir(), 0755);

#ifndef _XBOX
	if (is_daemon)
		pidfile_create("smbd");
#endif

	/* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */
	if (!message_init())
		exit(1);

	/* Initialize our global sam sid first -- quite a lot of the other
	 * initialization routines further down depend on it.
	 */

	/* Initialise the password backed before the global_sam_sid
	   to ensure that we fetch from ldap before we make a domain sid up */

	if(!initialize_password_db(False))
		exit(1);

	/* Fail gracefully if we can't open secrets.tdb */

	if (!secrets_init()) {
		DEBUG(0, ("ERROR: smbd can not open secrets.tdb\n"));
		exit(1);
	}

	if(!get_global_sam_sid()) {
		DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n"));
		exit(1);
	}

	if (!session_init())
		exit(1);

	if (conn_tdb_ctx() == NULL)
		exit(1);

	if (!locking_init(0))
		exit(1);

	namecache_enable();

	if (!init_registry())
		exit(1);

#if 0
	if (!init_svcctl_db())
                exit(1);
#endif

#ifndef _XBOX
	if (!print_backend_init())
		exit(1);
#endif

	if (!init_guest_info()) {
		DEBUG(0,("ERROR: failed to setup guest info.\n"));
		return -1;
	}

	/* Setup the main smbd so that we can get messages. */
	/* don't worry about general printing messages here */

	claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);

	/* only start the background queue daemon if we are 
	   running as a daemon -- bad things will happen if
	   smbd is launched via inetd and we fork a copy of 
	   ourselves here */
#ifndef _XBOX
	if ( is_daemon && !interactive )
		start_background_queue(); 
#endif
	/* 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
	 * session to work with.
	 */
	dmapi_init_session();

	if (!open_sockets_smbd(is_daemon, interactive, ports))
		exit(1);

	/*
	 * everything after this point is run after the fork()
	 */ 

	static_init_rpc;

	init_modules();

	/* possibly reload the services file. */
	reload_services(True);

	if (!init_account_policy()) {
		DEBUG(0,("Could not open account policy tdb.\n"));
		exit(1);
	}

	if (*lp_rootdir()) {
		if (sys_chroot(lp_rootdir()) == 0)
			DEBUG(2,("Changed root to %s\n", lp_rootdir()));
	}

	/* Setup oplocks */
	if (!init_oplocks())
		exit(1);
	
	/* Setup change notify */
	if (!init_change_notify())
		exit(1);

	/* Setup aio signal handler. */
	initialize_async_io_handler();

	/* re-initialise the timezone */
	TimeInit();

	/* register our message handlers */
	message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis);

	smbd_process();

#ifdef _XBOX
	xb_DecClientCount();
#endif

	namecache_shutdown();

	exit_server_cleanly(NULL);
	return(0);
}