mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
smbd: Move smbd_process to smb2_process.c
Signed-off-by: David Mulder <dmulder@suse.com> Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
parent
2e0e49f41b
commit
43672e1558
@ -708,76 +708,6 @@ bool push_deferred_open_message_smb1(struct smb_request *req,
|
||||
return push_queued_message(req, req->request_time, end_time, open_rec);
|
||||
}
|
||||
|
||||
static void smbd_sig_term_handler(struct tevent_context *ev,
|
||||
struct tevent_signal *se,
|
||||
int signum,
|
||||
int count,
|
||||
void *siginfo,
|
||||
void *private_data)
|
||||
{
|
||||
exit_server_cleanly("termination signal");
|
||||
}
|
||||
|
||||
static void smbd_setup_sig_term_handler(struct smbd_server_connection *sconn)
|
||||
{
|
||||
struct tevent_signal *se;
|
||||
|
||||
se = tevent_add_signal(sconn->ev_ctx,
|
||||
sconn,
|
||||
SIGTERM, 0,
|
||||
smbd_sig_term_handler,
|
||||
sconn);
|
||||
if (!se) {
|
||||
exit_server("failed to setup SIGTERM handler");
|
||||
}
|
||||
}
|
||||
|
||||
static void smbd_sig_hup_handler(struct tevent_context *ev,
|
||||
struct tevent_signal *se,
|
||||
int signum,
|
||||
int count,
|
||||
void *siginfo,
|
||||
void *private_data)
|
||||
{
|
||||
struct smbd_server_connection *sconn =
|
||||
talloc_get_type_abort(private_data,
|
||||
struct smbd_server_connection);
|
||||
|
||||
change_to_root_user();
|
||||
DEBUG(1,("Reloading services after SIGHUP\n"));
|
||||
reload_services(sconn, conn_snum_used, false);
|
||||
}
|
||||
|
||||
static void smbd_setup_sig_hup_handler(struct smbd_server_connection *sconn)
|
||||
{
|
||||
struct tevent_signal *se;
|
||||
|
||||
se = tevent_add_signal(sconn->ev_ctx,
|
||||
sconn,
|
||||
SIGHUP, 0,
|
||||
smbd_sig_hup_handler,
|
||||
sconn);
|
||||
if (!se) {
|
||||
exit_server("failed to setup SIGHUP handler");
|
||||
}
|
||||
}
|
||||
|
||||
static void smbd_conf_updated(struct messaging_context *msg,
|
||||
void *private_data,
|
||||
uint32_t msg_type,
|
||||
struct server_id server_id,
|
||||
DATA_BLOB *data)
|
||||
{
|
||||
struct smbd_server_connection *sconn =
|
||||
talloc_get_type_abort(private_data,
|
||||
struct smbd_server_connection);
|
||||
|
||||
DEBUG(10,("smbd_conf_updated: Got message saying smb.conf was "
|
||||
"updated. Reloading.\n"));
|
||||
change_to_root_user();
|
||||
reload_services(sconn, conn_snum_used, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Only allow 5 outstanding trans requests. We're allocating memory, so
|
||||
* prevent a DoS.
|
||||
@ -2117,23 +2047,6 @@ bool smb1_parse_chain(TALLOC_CTX *mem_ctx, const uint8_t *buf,
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Check if services need reloading.
|
||||
****************************************************************************/
|
||||
|
||||
static void check_reload(struct smbd_server_connection *sconn, time_t t)
|
||||
{
|
||||
|
||||
if (last_smb_conf_reload_time == 0) {
|
||||
last_smb_conf_reload_time = t;
|
||||
}
|
||||
|
||||
if (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK) {
|
||||
reload_services(sconn, conn_snum_used, true);
|
||||
last_smb_conf_reload_time = t;
|
||||
}
|
||||
}
|
||||
|
||||
static bool fd_is_readable(int fd)
|
||||
{
|
||||
int ret, revents;
|
||||
@ -2244,36 +2157,10 @@ static void smbd_server_echo_handler(struct tevent_context *ev,
|
||||
}
|
||||
}
|
||||
|
||||
static void msg_kill_client_ip(struct messaging_context *msg_ctx,
|
||||
void *private_data, uint32_t msg_type,
|
||||
struct server_id server_id, DATA_BLOB *data)
|
||||
{
|
||||
struct smbd_server_connection *sconn = talloc_get_type_abort(
|
||||
private_data, struct smbd_server_connection);
|
||||
const char *ip = (char *) data->data;
|
||||
char *client_ip;
|
||||
|
||||
DBG_DEBUG("Got kill request for client IP %s\n", ip);
|
||||
|
||||
client_ip = tsocket_address_inet_addr_string(sconn->remote_address,
|
||||
talloc_tos());
|
||||
if (client_ip == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strequal(ip, client_ip)) {
|
||||
DBG_WARNING("Got kill client message for %s - "
|
||||
"exiting immediately\n", ip);
|
||||
exit_server_cleanly("Forced disconnect for client");
|
||||
}
|
||||
|
||||
TALLOC_FREE(client_ip);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send keepalive packets to our client
|
||||
*/
|
||||
static bool keepalive_fn(const struct timeval *now, void *private_data)
|
||||
bool keepalive_fn(const struct timeval *now, void *private_data)
|
||||
{
|
||||
struct smbd_server_connection *sconn = talloc_get_type_abort(
|
||||
private_data, struct smbd_server_connection);
|
||||
@ -2309,50 +2196,6 @@ static bool keepalive_fn(const struct timeval *now, void *private_data)
|
||||
return True;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the recurring check if we're idle
|
||||
*/
|
||||
static bool deadtime_fn(const struct timeval *now, void *private_data)
|
||||
{
|
||||
struct smbd_server_connection *sconn =
|
||||
(struct smbd_server_connection *)private_data;
|
||||
|
||||
if ((conn_num_open(sconn) == 0)
|
||||
|| (conn_idle_all(sconn, now->tv_sec))) {
|
||||
DEBUG( 2, ( "Closing idle connection\n" ) );
|
||||
messaging_send(sconn->msg_ctx,
|
||||
messaging_server_id(sconn->msg_ctx),
|
||||
MSG_SHUTDOWN, &data_blob_null);
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the recurring log file and smb.conf reload checks.
|
||||
*/
|
||||
|
||||
static bool housekeeping_fn(const struct timeval *now, void *private_data)
|
||||
{
|
||||
struct smbd_server_connection *sconn = talloc_get_type_abort(
|
||||
private_data, struct smbd_server_connection);
|
||||
|
||||
DEBUG(5, ("housekeeping\n"));
|
||||
|
||||
change_to_root_user();
|
||||
|
||||
/* check if we need to reload services */
|
||||
check_reload(sconn, time_mono(NULL));
|
||||
|
||||
/*
|
||||
* Force a log file check.
|
||||
*/
|
||||
force_check_log_size();
|
||||
check_log_size();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read an smb packet in the echo handler child, giving the parent
|
||||
* smbd one second to react once the socket becomes readable.
|
||||
@ -2903,464 +2746,6 @@ fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool uid_in_use(struct auth_session_info *session_info,
|
||||
uid_t uid)
|
||||
{
|
||||
if (session_info->unix_token->uid == uid) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool gid_in_use(struct auth_session_info *session_info,
|
||||
gid_t gid)
|
||||
{
|
||||
uint32_t i;
|
||||
struct security_unix_token *utok = NULL;
|
||||
|
||||
utok = session_info->unix_token;
|
||||
if (utok->gid == gid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for(i = 0; i < utok->ngroups; i++) {
|
||||
if (utok->groups[i] == gid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool sid_in_use(struct auth_session_info *session_info,
|
||||
const struct dom_sid *psid)
|
||||
{
|
||||
struct security_token *tok = NULL;
|
||||
|
||||
tok = session_info->security_token;
|
||||
if (tok == NULL) {
|
||||
/*
|
||||
* Not sure session_info->security_token can
|
||||
* ever be NULL. This check might be not
|
||||
* necessary.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
if (security_token_has_sid(tok, psid)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct id_in_use_state {
|
||||
const struct id_cache_ref *id;
|
||||
bool match;
|
||||
};
|
||||
|
||||
static int id_in_use_cb(struct smbXsrv_session *session,
|
||||
void *private_data)
|
||||
{
|
||||
struct id_in_use_state *state = (struct id_in_use_state *)
|
||||
private_data;
|
||||
struct auth_session_info *session_info =
|
||||
session->global->auth_session_info;
|
||||
|
||||
switch(state->id->type) {
|
||||
case UID:
|
||||
state->match = uid_in_use(session_info, state->id->id.uid);
|
||||
break;
|
||||
case GID:
|
||||
state->match = gid_in_use(session_info, state->id->id.gid);
|
||||
break;
|
||||
case SID:
|
||||
state->match = sid_in_use(session_info, &state->id->id.sid);
|
||||
break;
|
||||
default:
|
||||
state->match = false;
|
||||
break;
|
||||
}
|
||||
if (state->match) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool id_in_use(struct smbd_server_connection *sconn,
|
||||
const struct id_cache_ref *id)
|
||||
{
|
||||
struct id_in_use_state state;
|
||||
NTSTATUS status;
|
||||
|
||||
state = (struct id_in_use_state) {
|
||||
.id = id,
|
||||
.match = false,
|
||||
};
|
||||
|
||||
status = smbXsrv_session_local_traverse(sconn->client,
|
||||
id_in_use_cb,
|
||||
&state);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return state.match;
|
||||
}
|
||||
|
||||
static void smbd_id_cache_kill(struct messaging_context *msg_ctx,
|
||||
void *private_data,
|
||||
uint32_t msg_type,
|
||||
struct server_id server_id,
|
||||
DATA_BLOB* data)
|
||||
{
|
||||
const char *msg = (data && data->data)
|
||||
? (const char *)data->data : "<NULL>";
|
||||
struct id_cache_ref id;
|
||||
struct smbd_server_connection *sconn =
|
||||
talloc_get_type_abort(private_data,
|
||||
struct smbd_server_connection);
|
||||
|
||||
if (!id_cache_ref_parse(msg, &id)) {
|
||||
DEBUG(0, ("Invalid ?ID: %s\n", msg));
|
||||
return;
|
||||
}
|
||||
|
||||
if (id_in_use(sconn, &id)) {
|
||||
exit_server_cleanly(msg);
|
||||
}
|
||||
id_cache_delete_from_cache(&id);
|
||||
}
|
||||
|
||||
struct smbd_tevent_trace_state {
|
||||
struct tevent_context *ev;
|
||||
TALLOC_CTX *frame;
|
||||
SMBPROFILE_BASIC_ASYNC_STATE(profile_idle);
|
||||
};
|
||||
|
||||
static void smbd_tevent_trace_callback(enum tevent_trace_point point,
|
||||
void *private_data)
|
||||
{
|
||||
struct smbd_tevent_trace_state *state =
|
||||
(struct smbd_tevent_trace_state *)private_data;
|
||||
|
||||
switch (point) {
|
||||
case TEVENT_TRACE_BEFORE_WAIT:
|
||||
if (!smbprofile_dump_pending()) {
|
||||
/*
|
||||
* If there's no dump pending
|
||||
* we don't want to schedule a new 1 sec timer.
|
||||
*
|
||||
* Instead we want to sleep as long as nothing happens.
|
||||
*/
|
||||
smbprofile_dump_setup(NULL);
|
||||
}
|
||||
SMBPROFILE_BASIC_ASYNC_START(idle, profile_p, state->profile_idle);
|
||||
break;
|
||||
case TEVENT_TRACE_AFTER_WAIT:
|
||||
SMBPROFILE_BASIC_ASYNC_END(state->profile_idle);
|
||||
if (!smbprofile_dump_pending()) {
|
||||
/*
|
||||
* We need to flush our state after sleeping
|
||||
* (hopefully a long time).
|
||||
*/
|
||||
smbprofile_dump();
|
||||
/*
|
||||
* future profiling events should trigger timers
|
||||
* on our main event context.
|
||||
*/
|
||||
smbprofile_dump_setup(state->ev);
|
||||
}
|
||||
break;
|
||||
case TEVENT_TRACE_BEFORE_LOOP_ONCE:
|
||||
TALLOC_FREE(state->frame);
|
||||
state->frame = talloc_stackframe_pool(8192);
|
||||
break;
|
||||
case TEVENT_TRACE_AFTER_LOOP_ONCE:
|
||||
TALLOC_FREE(state->frame);
|
||||
break;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Process commands from the client
|
||||
****************************************************************************/
|
||||
|
||||
void smbd_process(struct tevent_context *ev_ctx,
|
||||
struct messaging_context *msg_ctx,
|
||||
int sock_fd,
|
||||
bool interactive)
|
||||
{
|
||||
struct smbd_tevent_trace_state trace_state = {
|
||||
.ev = ev_ctx,
|
||||
.frame = talloc_stackframe(),
|
||||
};
|
||||
const struct loadparm_substitution *lp_sub =
|
||||
loadparm_s3_global_substitution();
|
||||
struct smbXsrv_client *client = NULL;
|
||||
struct smbd_server_connection *sconn = NULL;
|
||||
struct smbXsrv_connection *xconn = NULL;
|
||||
const char *locaddr = NULL;
|
||||
const char *remaddr = NULL;
|
||||
int ret;
|
||||
NTSTATUS status;
|
||||
struct timeval tv = timeval_current();
|
||||
NTTIME now = timeval_to_nttime(&tv);
|
||||
char *chroot_dir = NULL;
|
||||
int rc;
|
||||
|
||||
status = smbXsrv_client_create(ev_ctx, ev_ctx, msg_ctx, now, &client);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DBG_ERR("smbXsrv_client_create(): %s\n", nt_errstr(status));
|
||||
exit_server_cleanly("talloc_zero(struct smbXsrv_client).\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: remove this...:-)
|
||||
*/
|
||||
global_smbXsrv_client = client;
|
||||
|
||||
sconn = talloc_zero(client, struct smbd_server_connection);
|
||||
if (sconn == NULL) {
|
||||
exit_server("failed to create smbd_server_connection");
|
||||
}
|
||||
|
||||
client->sconn = sconn;
|
||||
sconn->client = client;
|
||||
|
||||
sconn->ev_ctx = ev_ctx;
|
||||
sconn->msg_ctx = msg_ctx;
|
||||
|
||||
ret = pthreadpool_tevent_init(sconn, lp_aio_max_threads(),
|
||||
&sconn->pool);
|
||||
if (ret != 0) {
|
||||
exit_server("pthreadpool_tevent_init() failed.");
|
||||
}
|
||||
|
||||
#if defined(WITH_SMB1SERVER)
|
||||
if (lp_server_max_protocol() >= PROTOCOL_SMB2_02) {
|
||||
#endif
|
||||
/*
|
||||
* We're not making the decision here,
|
||||
* we're just allowing the client
|
||||
* to decide between SMB1 and SMB2
|
||||
* with the first negprot
|
||||
* packet.
|
||||
*/
|
||||
sconn->using_smb2 = true;
|
||||
#if defined(WITH_SMB1SERVER)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!interactive) {
|
||||
smbd_setup_sig_term_handler(sconn);
|
||||
smbd_setup_sig_hup_handler(sconn);
|
||||
}
|
||||
|
||||
status = smbd_add_connection(client, sock_fd, now, &xconn);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
|
||||
/*
|
||||
* send a negative session response "not listening on calling
|
||||
* name"
|
||||
*/
|
||||
unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
|
||||
(void)srv_send_smb(xconn,(char *)buf, false,
|
||||
0, false, NULL);
|
||||
exit_server_cleanly("connection denied");
|
||||
} else if (!NT_STATUS_IS_OK(status)) {
|
||||
exit_server_cleanly(nt_errstr(status));
|
||||
}
|
||||
|
||||
sconn->local_address =
|
||||
tsocket_address_copy(xconn->local_address, sconn);
|
||||
if (sconn->local_address == NULL) {
|
||||
exit_server_cleanly("tsocket_address_copy() failed");
|
||||
}
|
||||
sconn->remote_address =
|
||||
tsocket_address_copy(xconn->remote_address, sconn);
|
||||
if (sconn->remote_address == NULL) {
|
||||
exit_server_cleanly("tsocket_address_copy() failed");
|
||||
}
|
||||
sconn->remote_hostname =
|
||||
talloc_strdup(sconn, xconn->remote_hostname);
|
||||
if (sconn->remote_hostname == NULL) {
|
||||
exit_server_cleanly("tsocket_strdup() failed");
|
||||
}
|
||||
|
||||
client->global->local_address =
|
||||
tsocket_address_string(sconn->local_address,
|
||||
client->global);
|
||||
if (client->global->local_address == NULL) {
|
||||
exit_server_cleanly("tsocket_address_string() failed");
|
||||
}
|
||||
client->global->remote_address =
|
||||
tsocket_address_string(sconn->remote_address,
|
||||
client->global);
|
||||
if (client->global->remote_address == NULL) {
|
||||
exit_server_cleanly("tsocket_address_string() failed");
|
||||
}
|
||||
client->global->remote_name =
|
||||
talloc_strdup(client->global, sconn->remote_hostname);
|
||||
if (client->global->remote_name == NULL) {
|
||||
exit_server_cleanly("tsocket_strdup() failed");
|
||||
}
|
||||
|
||||
if (tsocket_address_is_inet(sconn->local_address, "ip")) {
|
||||
locaddr = tsocket_address_inet_addr_string(
|
||||
sconn->local_address,
|
||||
talloc_tos());
|
||||
if (locaddr == NULL) {
|
||||
DEBUG(0,("%s: tsocket_address_inet_addr_string remote failed - %s\n",
|
||||
__location__, strerror(errno)));
|
||||
exit_server_cleanly("tsocket_address_inet_addr_string remote failed.\n");
|
||||
}
|
||||
} else {
|
||||
locaddr = "0.0.0.0";
|
||||
}
|
||||
|
||||
if (tsocket_address_is_inet(sconn->remote_address, "ip")) {
|
||||
remaddr = tsocket_address_inet_addr_string(
|
||||
sconn->remote_address,
|
||||
talloc_tos());
|
||||
if (remaddr == NULL) {
|
||||
DEBUG(0,("%s: tsocket_address_inet_addr_string remote failed - %s\n",
|
||||
__location__, strerror(errno)));
|
||||
exit_server_cleanly("tsocket_address_inet_addr_string remote failed.\n");
|
||||
}
|
||||
} else {
|
||||
remaddr = "0.0.0.0";
|
||||
}
|
||||
|
||||
/* this is needed so that we get decent entries
|
||||
in smbstatus for port 445 connects */
|
||||
set_remote_machine_name(remaddr, false);
|
||||
reload_services(sconn, conn_snum_used, true);
|
||||
sub_set_socket_ids(remaddr,
|
||||
sconn->remote_hostname,
|
||||
locaddr);
|
||||
|
||||
if (lp_preload_modules()) {
|
||||
smb_load_all_modules_absoute_path(lp_preload_modules());
|
||||
}
|
||||
|
||||
smb_perfcount_init();
|
||||
|
||||
if (!init_account_policy()) {
|
||||
exit_server("Could not open account policy tdb.\n");
|
||||
}
|
||||
|
||||
chroot_dir = lp_root_directory(talloc_tos(), lp_sub);
|
||||
if (chroot_dir[0] != '\0') {
|
||||
rc = chdir(chroot_dir);
|
||||
if (rc != 0) {
|
||||
DBG_ERR("Failed to chdir to %s\n", chroot_dir);
|
||||
exit_server("Failed to chdir()");
|
||||
}
|
||||
|
||||
rc = chroot(chroot_dir);
|
||||
if (rc != 0) {
|
||||
DBG_ERR("Failed to change root to %s\n", chroot_dir);
|
||||
exit_server("Failed to chroot()");
|
||||
}
|
||||
DBG_WARNING("Changed root to %s\n", chroot_dir);
|
||||
|
||||
TALLOC_FREE(chroot_dir);
|
||||
}
|
||||
|
||||
if (!file_init(sconn)) {
|
||||
exit_server("file_init() failed");
|
||||
}
|
||||
|
||||
/* Setup oplocks */
|
||||
if (!init_oplocks(sconn))
|
||||
exit_server("Failed to init oplocks");
|
||||
|
||||
/* register our message handlers */
|
||||
messaging_register(sconn->msg_ctx, sconn,
|
||||
MSG_SMB_FORCE_TDIS, msg_force_tdis);
|
||||
messaging_register(
|
||||
sconn->msg_ctx,
|
||||
sconn,
|
||||
MSG_SMB_FORCE_TDIS_DENIED,
|
||||
msg_force_tdis_denied);
|
||||
messaging_register(sconn->msg_ctx, sconn,
|
||||
MSG_SMB_CLOSE_FILE, msg_close_file);
|
||||
messaging_register(sconn->msg_ctx, sconn,
|
||||
MSG_SMB_FILE_RENAME, msg_file_was_renamed);
|
||||
|
||||
id_cache_register_msgs(sconn->msg_ctx);
|
||||
messaging_deregister(sconn->msg_ctx, ID_CACHE_KILL, NULL);
|
||||
messaging_register(sconn->msg_ctx, sconn,
|
||||
ID_CACHE_KILL, smbd_id_cache_kill);
|
||||
|
||||
messaging_deregister(sconn->msg_ctx,
|
||||
MSG_SMB_CONF_UPDATED, sconn->ev_ctx);
|
||||
messaging_register(sconn->msg_ctx, sconn,
|
||||
MSG_SMB_CONF_UPDATED, smbd_conf_updated);
|
||||
|
||||
messaging_deregister(sconn->msg_ctx, MSG_SMB_KILL_CLIENT_IP,
|
||||
NULL);
|
||||
messaging_register(sconn->msg_ctx, sconn,
|
||||
MSG_SMB_KILL_CLIENT_IP,
|
||||
msg_kill_client_ip);
|
||||
|
||||
messaging_deregister(sconn->msg_ctx, MSG_SMB_TELL_NUM_CHILDREN, NULL);
|
||||
|
||||
/*
|
||||
* Use the default MSG_DEBUG handler to avoid rebroadcasting
|
||||
* MSGs to all child processes
|
||||
*/
|
||||
messaging_deregister(sconn->msg_ctx,
|
||||
MSG_DEBUG, NULL);
|
||||
messaging_register(sconn->msg_ctx, NULL,
|
||||
MSG_DEBUG, debug_message);
|
||||
|
||||
#if defined(WITH_SMB1SERVER)
|
||||
if ((lp_keepalive() != 0)
|
||||
&& !(event_add_idle(ev_ctx, NULL,
|
||||
timeval_set(lp_keepalive(), 0),
|
||||
"keepalive", keepalive_fn,
|
||||
sconn))) {
|
||||
DEBUG(0, ("Could not add keepalive event\n"));
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(event_add_idle(ev_ctx, NULL,
|
||||
timeval_set(IDLE_CLOSED_TIMEOUT, 0),
|
||||
"deadtime", deadtime_fn, sconn))) {
|
||||
DEBUG(0, ("Could not add deadtime event\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!(event_add_idle(ev_ctx, NULL,
|
||||
timeval_set(SMBD_HOUSEKEEPING_INTERVAL, 0),
|
||||
"housekeeping", housekeeping_fn, sconn))) {
|
||||
DEBUG(0, ("Could not add housekeeping event\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
smbprofile_dump_setup(ev_ctx);
|
||||
|
||||
if (!init_dptrs(sconn)) {
|
||||
exit_server("init_dptrs() failed");
|
||||
}
|
||||
|
||||
TALLOC_FREE(trace_state.frame);
|
||||
|
||||
tevent_set_trace_callback(ev_ctx, smbd_tevent_trace_callback,
|
||||
&trace_state);
|
||||
|
||||
ret = tevent_loop_wait(ev_ctx);
|
||||
if (ret != 0) {
|
||||
DEBUG(1, ("tevent_loop_wait failed: %d, %s,"
|
||||
" exiting\n", ret, strerror(errno)));
|
||||
}
|
||||
|
||||
TALLOC_FREE(trace_state.frame);
|
||||
|
||||
exit_server_cleanly(NULL);
|
||||
}
|
||||
|
||||
bool req_is_in_chain(const struct smb_request *req)
|
||||
{
|
||||
if (req->vwv != (const uint16_t *)(req->inbuf+smb_vwv)) {
|
||||
|
@ -870,10 +870,6 @@ bool smb1_parse_chain(TALLOC_CTX *mem_ctx, const uint8_t *buf,
|
||||
bool encrypted, uint32_t seqnum,
|
||||
struct smb_request ***reqs, unsigned *num_reqs);
|
||||
bool req_is_in_chain(const struct smb_request *req);
|
||||
void smbd_process(struct tevent_context *ev_ctx,
|
||||
struct messaging_context *msg_ctx,
|
||||
int sock_fd,
|
||||
bool interactive);
|
||||
bool fork_echo_handler(struct smbXsrv_connection *xconn);
|
||||
NTSTATUS smb1_receive_talloc(TALLOC_CTX *mem_ctx,
|
||||
struct smbXsrv_connection *xconn,
|
||||
@ -899,6 +895,7 @@ void construct_reply(struct smbXsrv_connection *xconn,
|
||||
struct smb_perfcount_data *deferred_pcd);
|
||||
void smbd_smb1_server_connection_read_handler(struct smbXsrv_connection *xconn,
|
||||
int fd);
|
||||
bool keepalive_fn(const struct timeval *now, void *private_data);
|
||||
|
||||
/* The following definitions come from smbd/smb2_process.c */
|
||||
|
||||
@ -941,6 +938,10 @@ void process_smb(struct smbXsrv_connection *xconn,
|
||||
uint8_t *inbuf, size_t nread, size_t unread_bytes,
|
||||
uint32_t seqnum, bool encrypted,
|
||||
struct smb_perfcount_data *deferred_pcd);
|
||||
void smbd_process(struct tevent_context *ev_ctx,
|
||||
struct messaging_context *msg_ctx,
|
||||
int sock_fd,
|
||||
bool interactive);
|
||||
|
||||
/* The following definitions come from smbd/quotas.c */
|
||||
|
||||
|
@ -1284,3 +1284,618 @@ NTSTATUS smbd_add_connection(struct smbXsrv_client *client, int sock_fd,
|
||||
TALLOC_FREE(frame);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static bool uid_in_use(struct auth_session_info *session_info,
|
||||
uid_t uid)
|
||||
{
|
||||
if (session_info->unix_token->uid == uid) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool gid_in_use(struct auth_session_info *session_info,
|
||||
gid_t gid)
|
||||
{
|
||||
uint32_t i;
|
||||
struct security_unix_token *utok = NULL;
|
||||
|
||||
utok = session_info->unix_token;
|
||||
if (utok->gid == gid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for(i = 0; i < utok->ngroups; i++) {
|
||||
if (utok->groups[i] == gid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool sid_in_use(struct auth_session_info *session_info,
|
||||
const struct dom_sid *psid)
|
||||
{
|
||||
struct security_token *tok = NULL;
|
||||
|
||||
tok = session_info->security_token;
|
||||
if (tok == NULL) {
|
||||
/*
|
||||
* Not sure session_info->security_token can
|
||||
* ever be NULL. This check might be not
|
||||
* necessary.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
if (security_token_has_sid(tok, psid)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct id_in_use_state {
|
||||
const struct id_cache_ref *id;
|
||||
bool match;
|
||||
};
|
||||
|
||||
static int id_in_use_cb(struct smbXsrv_session *session,
|
||||
void *private_data)
|
||||
{
|
||||
struct id_in_use_state *state = (struct id_in_use_state *)
|
||||
private_data;
|
||||
struct auth_session_info *session_info =
|
||||
session->global->auth_session_info;
|
||||
|
||||
switch(state->id->type) {
|
||||
case UID:
|
||||
state->match = uid_in_use(session_info, state->id->id.uid);
|
||||
break;
|
||||
case GID:
|
||||
state->match = gid_in_use(session_info, state->id->id.gid);
|
||||
break;
|
||||
case SID:
|
||||
state->match = sid_in_use(session_info, &state->id->id.sid);
|
||||
break;
|
||||
default:
|
||||
state->match = false;
|
||||
break;
|
||||
}
|
||||
if (state->match) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool id_in_use(struct smbd_server_connection *sconn,
|
||||
const struct id_cache_ref *id)
|
||||
{
|
||||
struct id_in_use_state state;
|
||||
NTSTATUS status;
|
||||
|
||||
state = (struct id_in_use_state) {
|
||||
.id = id,
|
||||
.match = false,
|
||||
};
|
||||
|
||||
status = smbXsrv_session_local_traverse(sconn->client,
|
||||
id_in_use_cb,
|
||||
&state);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return state.match;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Check if services need reloading.
|
||||
****************************************************************************/
|
||||
|
||||
static void check_reload(struct smbd_server_connection *sconn, time_t t)
|
||||
{
|
||||
|
||||
if (last_smb_conf_reload_time == 0) {
|
||||
last_smb_conf_reload_time = t;
|
||||
}
|
||||
|
||||
if (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK) {
|
||||
reload_services(sconn, conn_snum_used, true);
|
||||
last_smb_conf_reload_time = t;
|
||||
}
|
||||
}
|
||||
|
||||
static void msg_kill_client_ip(struct messaging_context *msg_ctx,
|
||||
void *private_data, uint32_t msg_type,
|
||||
struct server_id server_id, DATA_BLOB *data)
|
||||
{
|
||||
struct smbd_server_connection *sconn = talloc_get_type_abort(
|
||||
private_data, struct smbd_server_connection);
|
||||
const char *ip = (char *) data->data;
|
||||
char *client_ip;
|
||||
|
||||
DBG_DEBUG("Got kill request for client IP %s\n", ip);
|
||||
|
||||
client_ip = tsocket_address_inet_addr_string(sconn->remote_address,
|
||||
talloc_tos());
|
||||
if (client_ip == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strequal(ip, client_ip)) {
|
||||
DBG_WARNING("Got kill client message for %s - "
|
||||
"exiting immediately\n", ip);
|
||||
exit_server_cleanly("Forced disconnect for client");
|
||||
}
|
||||
|
||||
TALLOC_FREE(client_ip);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the recurring check if we're idle
|
||||
*/
|
||||
static bool deadtime_fn(const struct timeval *now, void *private_data)
|
||||
{
|
||||
struct smbd_server_connection *sconn =
|
||||
(struct smbd_server_connection *)private_data;
|
||||
|
||||
if ((conn_num_open(sconn) == 0)
|
||||
|| (conn_idle_all(sconn, now->tv_sec))) {
|
||||
DEBUG( 2, ( "Closing idle connection\n" ) );
|
||||
messaging_send(sconn->msg_ctx,
|
||||
messaging_server_id(sconn->msg_ctx),
|
||||
MSG_SHUTDOWN, &data_blob_null);
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the recurring log file and smb.conf reload checks.
|
||||
*/
|
||||
|
||||
static bool housekeeping_fn(const struct timeval *now, void *private_data)
|
||||
{
|
||||
struct smbd_server_connection *sconn = talloc_get_type_abort(
|
||||
private_data, struct smbd_server_connection);
|
||||
|
||||
DEBUG(5, ("housekeeping\n"));
|
||||
|
||||
change_to_root_user();
|
||||
|
||||
/* check if we need to reload services */
|
||||
check_reload(sconn, time_mono(NULL));
|
||||
|
||||
/*
|
||||
* Force a log file check.
|
||||
*/
|
||||
force_check_log_size();
|
||||
check_log_size();
|
||||
return true;
|
||||
}
|
||||
|
||||
static void smbd_sig_term_handler(struct tevent_context *ev,
|
||||
struct tevent_signal *se,
|
||||
int signum,
|
||||
int count,
|
||||
void *siginfo,
|
||||
void *private_data)
|
||||
{
|
||||
exit_server_cleanly("termination signal");
|
||||
}
|
||||
|
||||
static void smbd_setup_sig_term_handler(struct smbd_server_connection *sconn)
|
||||
{
|
||||
struct tevent_signal *se;
|
||||
|
||||
se = tevent_add_signal(sconn->ev_ctx,
|
||||
sconn,
|
||||
SIGTERM, 0,
|
||||
smbd_sig_term_handler,
|
||||
sconn);
|
||||
if (!se) {
|
||||
exit_server("failed to setup SIGTERM handler");
|
||||
}
|
||||
}
|
||||
|
||||
static void smbd_sig_hup_handler(struct tevent_context *ev,
|
||||
struct tevent_signal *se,
|
||||
int signum,
|
||||
int count,
|
||||
void *siginfo,
|
||||
void *private_data)
|
||||
{
|
||||
struct smbd_server_connection *sconn =
|
||||
talloc_get_type_abort(private_data,
|
||||
struct smbd_server_connection);
|
||||
|
||||
change_to_root_user();
|
||||
DEBUG(1,("Reloading services after SIGHUP\n"));
|
||||
reload_services(sconn, conn_snum_used, false);
|
||||
}
|
||||
|
||||
static void smbd_setup_sig_hup_handler(struct smbd_server_connection *sconn)
|
||||
{
|
||||
struct tevent_signal *se;
|
||||
|
||||
se = tevent_add_signal(sconn->ev_ctx,
|
||||
sconn,
|
||||
SIGHUP, 0,
|
||||
smbd_sig_hup_handler,
|
||||
sconn);
|
||||
if (!se) {
|
||||
exit_server("failed to setup SIGHUP handler");
|
||||
}
|
||||
}
|
||||
|
||||
static void smbd_conf_updated(struct messaging_context *msg,
|
||||
void *private_data,
|
||||
uint32_t msg_type,
|
||||
struct server_id server_id,
|
||||
DATA_BLOB *data)
|
||||
{
|
||||
struct smbd_server_connection *sconn =
|
||||
talloc_get_type_abort(private_data,
|
||||
struct smbd_server_connection);
|
||||
|
||||
DEBUG(10,("smbd_conf_updated: Got message saying smb.conf was "
|
||||
"updated. Reloading.\n"));
|
||||
change_to_root_user();
|
||||
reload_services(sconn, conn_snum_used, false);
|
||||
}
|
||||
|
||||
static void smbd_id_cache_kill(struct messaging_context *msg_ctx,
|
||||
void *private_data,
|
||||
uint32_t msg_type,
|
||||
struct server_id server_id,
|
||||
DATA_BLOB* data)
|
||||
{
|
||||
const char *msg = (data && data->data)
|
||||
? (const char *)data->data : "<NULL>";
|
||||
struct id_cache_ref id;
|
||||
struct smbd_server_connection *sconn =
|
||||
talloc_get_type_abort(private_data,
|
||||
struct smbd_server_connection);
|
||||
|
||||
if (!id_cache_ref_parse(msg, &id)) {
|
||||
DEBUG(0, ("Invalid ?ID: %s\n", msg));
|
||||
return;
|
||||
}
|
||||
|
||||
if (id_in_use(sconn, &id)) {
|
||||
exit_server_cleanly(msg);
|
||||
}
|
||||
id_cache_delete_from_cache(&id);
|
||||
}
|
||||
|
||||
struct smbd_tevent_trace_state {
|
||||
struct tevent_context *ev;
|
||||
TALLOC_CTX *frame;
|
||||
SMBPROFILE_BASIC_ASYNC_STATE(profile_idle);
|
||||
};
|
||||
|
||||
static void smbd_tevent_trace_callback(enum tevent_trace_point point,
|
||||
void *private_data)
|
||||
{
|
||||
struct smbd_tevent_trace_state *state =
|
||||
(struct smbd_tevent_trace_state *)private_data;
|
||||
|
||||
switch (point) {
|
||||
case TEVENT_TRACE_BEFORE_WAIT:
|
||||
if (!smbprofile_dump_pending()) {
|
||||
/*
|
||||
* If there's no dump pending
|
||||
* we don't want to schedule a new 1 sec timer.
|
||||
*
|
||||
* Instead we want to sleep as long as nothing happens.
|
||||
*/
|
||||
smbprofile_dump_setup(NULL);
|
||||
}
|
||||
SMBPROFILE_BASIC_ASYNC_START(idle, profile_p, state->profile_idle);
|
||||
break;
|
||||
case TEVENT_TRACE_AFTER_WAIT:
|
||||
SMBPROFILE_BASIC_ASYNC_END(state->profile_idle);
|
||||
if (!smbprofile_dump_pending()) {
|
||||
/*
|
||||
* We need to flush our state after sleeping
|
||||
* (hopefully a long time).
|
||||
*/
|
||||
smbprofile_dump();
|
||||
/*
|
||||
* future profiling events should trigger timers
|
||||
* on our main event context.
|
||||
*/
|
||||
smbprofile_dump_setup(state->ev);
|
||||
}
|
||||
break;
|
||||
case TEVENT_TRACE_BEFORE_LOOP_ONCE:
|
||||
TALLOC_FREE(state->frame);
|
||||
state->frame = talloc_stackframe_pool(8192);
|
||||
break;
|
||||
case TEVENT_TRACE_AFTER_LOOP_ONCE:
|
||||
TALLOC_FREE(state->frame);
|
||||
break;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Process commands from the client
|
||||
****************************************************************************/
|
||||
|
||||
void smbd_process(struct tevent_context *ev_ctx,
|
||||
struct messaging_context *msg_ctx,
|
||||
int sock_fd,
|
||||
bool interactive)
|
||||
{
|
||||
struct smbd_tevent_trace_state trace_state = {
|
||||
.ev = ev_ctx,
|
||||
.frame = talloc_stackframe(),
|
||||
};
|
||||
const struct loadparm_substitution *lp_sub =
|
||||
loadparm_s3_global_substitution();
|
||||
struct smbXsrv_client *client = NULL;
|
||||
struct smbd_server_connection *sconn = NULL;
|
||||
struct smbXsrv_connection *xconn = NULL;
|
||||
const char *locaddr = NULL;
|
||||
const char *remaddr = NULL;
|
||||
int ret;
|
||||
NTSTATUS status;
|
||||
struct timeval tv = timeval_current();
|
||||
NTTIME now = timeval_to_nttime(&tv);
|
||||
char *chroot_dir = NULL;
|
||||
int rc;
|
||||
|
||||
status = smbXsrv_client_create(ev_ctx, ev_ctx, msg_ctx, now, &client);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DBG_ERR("smbXsrv_client_create(): %s\n", nt_errstr(status));
|
||||
exit_server_cleanly("talloc_zero(struct smbXsrv_client).\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: remove this...:-)
|
||||
*/
|
||||
global_smbXsrv_client = client;
|
||||
|
||||
sconn = talloc_zero(client, struct smbd_server_connection);
|
||||
if (sconn == NULL) {
|
||||
exit_server("failed to create smbd_server_connection");
|
||||
}
|
||||
|
||||
client->sconn = sconn;
|
||||
sconn->client = client;
|
||||
|
||||
sconn->ev_ctx = ev_ctx;
|
||||
sconn->msg_ctx = msg_ctx;
|
||||
|
||||
ret = pthreadpool_tevent_init(sconn, lp_aio_max_threads(),
|
||||
&sconn->pool);
|
||||
if (ret != 0) {
|
||||
exit_server("pthreadpool_tevent_init() failed.");
|
||||
}
|
||||
|
||||
#if defined(WITH_SMB1SERVER)
|
||||
if (lp_server_max_protocol() >= PROTOCOL_SMB2_02) {
|
||||
#endif
|
||||
/*
|
||||
* We're not making the decision here,
|
||||
* we're just allowing the client
|
||||
* to decide between SMB1 and SMB2
|
||||
* with the first negprot
|
||||
* packet.
|
||||
*/
|
||||
sconn->using_smb2 = true;
|
||||
#if defined(WITH_SMB1SERVER)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!interactive) {
|
||||
smbd_setup_sig_term_handler(sconn);
|
||||
smbd_setup_sig_hup_handler(sconn);
|
||||
}
|
||||
|
||||
status = smbd_add_connection(client, sock_fd, now, &xconn);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
|
||||
/*
|
||||
* send a negative session response "not listening on calling
|
||||
* name"
|
||||
*/
|
||||
unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
|
||||
(void)srv_send_smb(xconn,(char *)buf, false,
|
||||
0, false, NULL);
|
||||
exit_server_cleanly("connection denied");
|
||||
} else if (!NT_STATUS_IS_OK(status)) {
|
||||
exit_server_cleanly(nt_errstr(status));
|
||||
}
|
||||
|
||||
sconn->local_address =
|
||||
tsocket_address_copy(xconn->local_address, sconn);
|
||||
if (sconn->local_address == NULL) {
|
||||
exit_server_cleanly("tsocket_address_copy() failed");
|
||||
}
|
||||
sconn->remote_address =
|
||||
tsocket_address_copy(xconn->remote_address, sconn);
|
||||
if (sconn->remote_address == NULL) {
|
||||
exit_server_cleanly("tsocket_address_copy() failed");
|
||||
}
|
||||
sconn->remote_hostname =
|
||||
talloc_strdup(sconn, xconn->remote_hostname);
|
||||
if (sconn->remote_hostname == NULL) {
|
||||
exit_server_cleanly("tsocket_strdup() failed");
|
||||
}
|
||||
|
||||
client->global->local_address =
|
||||
tsocket_address_string(sconn->local_address,
|
||||
client->global);
|
||||
if (client->global->local_address == NULL) {
|
||||
exit_server_cleanly("tsocket_address_string() failed");
|
||||
}
|
||||
client->global->remote_address =
|
||||
tsocket_address_string(sconn->remote_address,
|
||||
client->global);
|
||||
if (client->global->remote_address == NULL) {
|
||||
exit_server_cleanly("tsocket_address_string() failed");
|
||||
}
|
||||
client->global->remote_name =
|
||||
talloc_strdup(client->global, sconn->remote_hostname);
|
||||
if (client->global->remote_name == NULL) {
|
||||
exit_server_cleanly("tsocket_strdup() failed");
|
||||
}
|
||||
|
||||
if (tsocket_address_is_inet(sconn->local_address, "ip")) {
|
||||
locaddr = tsocket_address_inet_addr_string(
|
||||
sconn->local_address,
|
||||
talloc_tos());
|
||||
if (locaddr == NULL) {
|
||||
DEBUG(0,("%s: tsocket_address_inet_addr_string remote failed - %s\n",
|
||||
__location__, strerror(errno)));
|
||||
exit_server_cleanly("tsocket_address_inet_addr_string remote failed.\n");
|
||||
}
|
||||
} else {
|
||||
locaddr = "0.0.0.0";
|
||||
}
|
||||
|
||||
if (tsocket_address_is_inet(sconn->remote_address, "ip")) {
|
||||
remaddr = tsocket_address_inet_addr_string(
|
||||
sconn->remote_address,
|
||||
talloc_tos());
|
||||
if (remaddr == NULL) {
|
||||
DEBUG(0,("%s: tsocket_address_inet_addr_string remote failed - %s\n",
|
||||
__location__, strerror(errno)));
|
||||
exit_server_cleanly("tsocket_address_inet_addr_string remote failed.\n");
|
||||
}
|
||||
} else {
|
||||
remaddr = "0.0.0.0";
|
||||
}
|
||||
|
||||
/* this is needed so that we get decent entries
|
||||
in smbstatus for port 445 connects */
|
||||
set_remote_machine_name(remaddr, false);
|
||||
reload_services(sconn, conn_snum_used, true);
|
||||
sub_set_socket_ids(remaddr,
|
||||
sconn->remote_hostname,
|
||||
locaddr);
|
||||
|
||||
if (lp_preload_modules()) {
|
||||
smb_load_all_modules_absoute_path(lp_preload_modules());
|
||||
}
|
||||
|
||||
smb_perfcount_init();
|
||||
|
||||
if (!init_account_policy()) {
|
||||
exit_server("Could not open account policy tdb.\n");
|
||||
}
|
||||
|
||||
chroot_dir = lp_root_directory(talloc_tos(), lp_sub);
|
||||
if (chroot_dir[0] != '\0') {
|
||||
rc = chdir(chroot_dir);
|
||||
if (rc != 0) {
|
||||
DBG_ERR("Failed to chdir to %s\n", chroot_dir);
|
||||
exit_server("Failed to chdir()");
|
||||
}
|
||||
|
||||
rc = chroot(chroot_dir);
|
||||
if (rc != 0) {
|
||||
DBG_ERR("Failed to change root to %s\n", chroot_dir);
|
||||
exit_server("Failed to chroot()");
|
||||
}
|
||||
DBG_WARNING("Changed root to %s\n", chroot_dir);
|
||||
|
||||
TALLOC_FREE(chroot_dir);
|
||||
}
|
||||
|
||||
if (!file_init(sconn)) {
|
||||
exit_server("file_init() failed");
|
||||
}
|
||||
|
||||
/* Setup oplocks */
|
||||
if (!init_oplocks(sconn))
|
||||
exit_server("Failed to init oplocks");
|
||||
|
||||
/* register our message handlers */
|
||||
messaging_register(sconn->msg_ctx, sconn,
|
||||
MSG_SMB_FORCE_TDIS, msg_force_tdis);
|
||||
messaging_register(
|
||||
sconn->msg_ctx,
|
||||
sconn,
|
||||
MSG_SMB_FORCE_TDIS_DENIED,
|
||||
msg_force_tdis_denied);
|
||||
messaging_register(sconn->msg_ctx, sconn,
|
||||
MSG_SMB_CLOSE_FILE, msg_close_file);
|
||||
messaging_register(sconn->msg_ctx, sconn,
|
||||
MSG_SMB_FILE_RENAME, msg_file_was_renamed);
|
||||
|
||||
id_cache_register_msgs(sconn->msg_ctx);
|
||||
messaging_deregister(sconn->msg_ctx, ID_CACHE_KILL, NULL);
|
||||
messaging_register(sconn->msg_ctx, sconn,
|
||||
ID_CACHE_KILL, smbd_id_cache_kill);
|
||||
|
||||
messaging_deregister(sconn->msg_ctx,
|
||||
MSG_SMB_CONF_UPDATED, sconn->ev_ctx);
|
||||
messaging_register(sconn->msg_ctx, sconn,
|
||||
MSG_SMB_CONF_UPDATED, smbd_conf_updated);
|
||||
|
||||
messaging_deregister(sconn->msg_ctx, MSG_SMB_KILL_CLIENT_IP,
|
||||
NULL);
|
||||
messaging_register(sconn->msg_ctx, sconn,
|
||||
MSG_SMB_KILL_CLIENT_IP,
|
||||
msg_kill_client_ip);
|
||||
|
||||
messaging_deregister(sconn->msg_ctx, MSG_SMB_TELL_NUM_CHILDREN, NULL);
|
||||
|
||||
/*
|
||||
* Use the default MSG_DEBUG handler to avoid rebroadcasting
|
||||
* MSGs to all child processes
|
||||
*/
|
||||
messaging_deregister(sconn->msg_ctx,
|
||||
MSG_DEBUG, NULL);
|
||||
messaging_register(sconn->msg_ctx, NULL,
|
||||
MSG_DEBUG, debug_message);
|
||||
|
||||
#if defined(WITH_SMB1SERVER)
|
||||
if ((lp_keepalive() != 0)
|
||||
&& !(event_add_idle(ev_ctx, NULL,
|
||||
timeval_set(lp_keepalive(), 0),
|
||||
"keepalive", keepalive_fn,
|
||||
sconn))) {
|
||||
DEBUG(0, ("Could not add keepalive event\n"));
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(event_add_idle(ev_ctx, NULL,
|
||||
timeval_set(IDLE_CLOSED_TIMEOUT, 0),
|
||||
"deadtime", deadtime_fn, sconn))) {
|
||||
DEBUG(0, ("Could not add deadtime event\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!(event_add_idle(ev_ctx, NULL,
|
||||
timeval_set(SMBD_HOUSEKEEPING_INTERVAL, 0),
|
||||
"housekeeping", housekeeping_fn, sconn))) {
|
||||
DEBUG(0, ("Could not add housekeeping event\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
smbprofile_dump_setup(ev_ctx);
|
||||
|
||||
if (!init_dptrs(sconn)) {
|
||||
exit_server("init_dptrs() failed");
|
||||
}
|
||||
|
||||
TALLOC_FREE(trace_state.frame);
|
||||
|
||||
tevent_set_trace_callback(ev_ctx, smbd_tevent_trace_callback,
|
||||
&trace_state);
|
||||
|
||||
ret = tevent_loop_wait(ev_ctx);
|
||||
if (ret != 0) {
|
||||
DEBUG(1, ("tevent_loop_wait failed: %d, %s,"
|
||||
" exiting\n", ret, strerror(errno)));
|
||||
}
|
||||
|
||||
TALLOC_FREE(trace_state.frame);
|
||||
|
||||
exit_server_cleanly(NULL);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user