Ejemplo n.º 1
0
void msg_close_file(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;
	files_struct *fsp = NULL;
	struct share_mode_entry e;

	sconn = msg_ctx_to_sconn(msg_ctx);
	if (sconn == NULL) {
		DEBUG(1, ("could not find sconn\n"));
		return;
	}

	message_to_share_mode_entry(&e, (char *)data->data);

	if(DEBUGLVL(10)) {
		char *sm_str = share_mode_str(NULL, 0, &e);
		if (!sm_str) {
			smb_panic("talloc failed");
		}
		DEBUG(10,("msg_close_file: got request to close share mode "
			"entry %s\n", sm_str));
		TALLOC_FREE(sm_str);
	}

	fsp = file_find_dif(sconn, e.id, e.share_file_id);
	if (!fsp) {
		DEBUG(10,("msg_close_file: failed to find file.\n"));
		return;
	}
	close_file(NULL, fsp, NORMAL_CLOSE);
}
Ejemplo n.º 2
0
static void received_unlock_msg(struct messaging_context *msg,
				void *private_data,
				uint32_t msg_type,
				struct server_id server_id,
				DATA_BLOB *data)
{
	struct smbd_server_connection *sconn;

	sconn = msg_ctx_to_sconn(msg);
	if (sconn == NULL) {
		DEBUG(1, ("could not find sconn\n"));
		return;
	}

	DEBUG(10,("received_unlock_msg\n"));
	process_blocking_lock_queue(sconn);
}
Ejemplo n.º 3
0
static void smb_conf_updated(struct messaging_context *msg,
			     void *private_data,
			     uint32_t msg_type,
			     struct server_id server_id,
			     DATA_BLOB *data)
{
	struct tevent_context *ev_ctx =
		talloc_get_type_abort(private_data, struct tevent_context);
	struct smbd_server_connection *sconn = msg_ctx_to_sconn(msg);

	DEBUG(10,("smb_conf_updated: Got message saying smb.conf was "
		  "updated. Reloading.\n"));
	change_to_root_user();
	reload_services(msg, sconn->sock, False);
	if (am_parent) {
		printing_subsystem_update(ev_ctx, msg, false);
	}
}
Ejemplo n.º 4
0
static void notify_deferred_opens(struct messaging_context *msg_ctx,
				  struct share_mode_lock *lck)
{
 	int i;

	if (!should_notify_deferred_opens()) {
		return;
	}

 	for (i=0; i<lck->num_share_modes; i++) {
 		struct share_mode_entry *e = &lck->share_modes[i];

 		if (!is_deferred_open_entry(e)) {
 			continue;
 		}

 		if (procid_is_me(&e->pid)) {
			struct smbd_server_connection *sconn;
 			/*
 			 * We need to notify ourself to retry the open.  Do
 			 * this by finding the queued SMB record, moving it to
 			 * the head of the queue and changing the wait time to
 			 * zero.
 			 */
			sconn = msg_ctx_to_sconn(msg_ctx);
			if (sconn != NULL) {
				schedule_deferred_open_message_smb(
					sconn, e->op_mid);
			}
 		} else {
			char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];

			share_mode_entry_to_message(msg, e);

			messaging_send_buf(msg_ctx, e->pid, MSG_SMB_OPEN_RETRY,
					   (uint8 *)msg,
					   MSG_SMB_SHARE_MODE_ENTRY_SIZE);
 		}
 	}
}
Ejemplo n.º 5
0
static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
						 void *private_data,
						 uint32_t msg_type,
						 struct server_id server_id,
						 DATA_BLOB *data)
{
	struct smbd_server_connection *sconn;
	NTSTATUS err;
	const char *msg = (const char *)data->data;
	struct blocking_lock_record *blr;

	if (data->data == NULL) {
		smb_panic("process_blocking_lock_cancel_message: null msg");
	}

	if (data->length != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
		DEBUG(0, ("process_blocking_lock_cancel_message: "
			  "Got invalid msg len %d\n", (int)data->length));
		smb_panic("process_blocking_lock_cancel_message: bad msg");
        }

	sconn = msg_ctx_to_sconn(ctx);
	if (sconn == NULL) {
		DEBUG(1, ("could not find sconn\n"));
		return;
	}

	memcpy(&blr, msg, sizeof(blr));
	memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));

	DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
		nt_errstr(err) ));

	blocking_lock_reply_error(blr, err);
	DLIST_REMOVE(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
	TALLOC_FREE(blr);
}
Ejemplo n.º 6
0
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();
}