static void smbd_accept_connection(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *private_data) { struct smbd_open_socket *s = talloc_get_type_abort(private_data, struct smbd_open_socket); struct messaging_context *msg_ctx = s->msg_ctx; struct smbd_server_connection *sconn = msg_ctx_to_sconn(msg_ctx); struct sockaddr_storage addr; socklen_t in_addrlen = sizeof(addr); int fd; pid_t pid = 0; uint64_t unique_id; fd = accept(s->fd, (struct sockaddr *)(void *)&addr,&in_addrlen); sconn->sock = fd; if (fd == -1 && errno == EINTR) return; if (fd == -1) { DEBUG(0,("open_sockets_smbd: accept: %s\n", strerror(errno))); return; } if (s->parent->interactive) { smbd_process(ev, sconn); exit_server_cleanly("end of interactive mode"); return; } if (!allowable_number_of_smbd_processes()) { close(fd); sconn->sock = -1; return; } /* * Generate a unique id in the parent process so that we use * the global random state in the parent. */ generate_random_buffer((uint8_t *)&unique_id, sizeof(unique_id)); pid = sys_fork(); if (pid == 0) { NTSTATUS status = NT_STATUS_OK; /* Child code ... */ am_parent = 0; set_my_unique_id(unique_id); /* Stop zombies, the parent explicitly handles * them, counting worker smbds. */ CatchChild(); /* close our standard file descriptors */ if (!debug_get_output_is_stdout()) { close_low_fds(False); /* Don't close stderr */ } /* * Can't use TALLOC_FREE here. Nulling out the argument to it * would overwrite memory we've just freed. */ talloc_free(s->parent); s = NULL; status = reinit_after_fork(msg_ctx, ev, procid_self(), true); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status, NT_STATUS_TOO_MANY_OPENED_FILES)) { DEBUG(0,("child process cannot initialize " "because too many files are open\n")); goto exit; } if (lp_clustering() && NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_DB_ERROR)) { DEBUG(1,("child process cannot initialize " "because connection to CTDB " "has failed\n")); goto exit; } DEBUG(0,("reinit_after_fork() failed\n")); smb_panic("reinit_after_fork() failed"); } smbd_setup_sig_term_handler(); smbd_setup_sig_hup_handler(ev, msg_ctx); if (!serverid_register(procid_self(), FLAG_MSG_GENERAL|FLAG_MSG_SMBD |FLAG_MSG_DBWRAP |FLAG_MSG_PRINT_GENERAL)) { exit_server_cleanly("Could not register myself in " "serverid.tdb"); } smbd_process(ev, sconn); exit: exit_server_cleanly("end of child"); return; } if (pid < 0) { DEBUG(0,("smbd_accept_connection: sys_fork() failed: %s\n", strerror(errno))); } /* The parent doesn't need this socket */ close(fd); /* Sun May 6 18:56:14 2001 [email protected]: Clear the closed fd info out of server_fd -- and more importantly, out of client_fd in util_sock.c, to avoid a possible getpeername failure if we reopen the logs and use %I in the filename. */ sconn->sock = -1; if (pid != 0) { add_child_pid(pid); } /* Force parent to check log size after * spawning child. Fix from * [email protected]. The * parent smbd will log to logserver.smb. It * writes only two messages for each child * started/finished. But each child writes, * say, 50 messages also in logserver.smb, * begining with the debug_count of the * parent, before the child opens its own log * file logserver.client. In a worst case * scenario the size of logserver.smb would be * checked after about 50*50=2500 messages * (ca. 100kb). * */ force_check_log_size(); }
static void smbd_accept_connection(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *private_data) { struct smbd_open_socket *s = talloc_get_type_abort(private_data, struct smbd_open_socket); struct messaging_context *msg_ctx = s->parent->msg_ctx; struct sockaddr_storage addr; socklen_t in_addrlen = sizeof(addr); int fd; pid_t pid = 0; fd = accept(s->fd, (struct sockaddr *)(void *)&addr,&in_addrlen); if (fd == -1 && errno == EINTR) return; if (fd == -1) { DEBUG(0,("accept: %s\n", strerror(errno))); return; } if (s->parent->interactive) { reinit_after_fork(msg_ctx, ev, true, NULL); smbd_process(ev, msg_ctx, fd, true); exit_server_cleanly("end of interactive mode"); return; } if (!allowable_number_of_smbd_processes(s->parent)) { close(fd); return; } pid = fork(); if (pid == 0) { NTSTATUS status = NT_STATUS_OK; /* * Can't use TALLOC_FREE here. Nulling out the argument to it * would overwrite memory we've just freed. */ talloc_free(s->parent); s = NULL; /* Stop zombies, the parent explicitly handles * them, counting worker smbds. */ CatchChild(); status = smbd_reinit_after_fork(msg_ctx, ev, true, NULL); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status, NT_STATUS_TOO_MANY_OPENED_FILES)) { DEBUG(0,("child process cannot initialize " "because too many files are open\n")); goto exit; } if (lp_clustering() && NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_DB_ERROR)) { DEBUG(1,("child process cannot initialize " "because connection to CTDB " "has failed\n")); goto exit; } DEBUG(0,("reinit_after_fork() failed\n")); smb_panic("reinit_after_fork() failed"); } smbd_process(ev, msg_ctx, fd, false); exit: exit_server_cleanly("end of child"); return; } if (pid < 0) { DEBUG(0,("smbd_accept_connection: fork() failed: %s\n", strerror(errno))); } /* The parent doesn't need this socket */ close(fd); /* Sun May 6 18:56:14 2001 [email protected]: Clear the closed fd info out of server_fd -- and more importantly, out of client_fd in util_sock.c, to avoid a possible getpeername failure if we reopen the logs and use %I in the filename. */ if (pid != 0) { add_child_pid(s->parent, pid); } /* Force parent to check log size after * spawning child. Fix from * [email protected]. The * parent smbd will log to logserver.smb. It * writes only two messages for each child * started/finished. But each child writes, * say, 50 messages also in logserver.smb, * begining with the debug_count of the * parent, before the child opens its own log * file logserver.client. In a worst case * scenario the size of logserver.smb would be * checked after about 50*50=2500 messages * (ca. 100kb). * */ force_check_log_size(); }