Beispiel #1
0
static int smbd_scavenger_main(struct smbd_scavenger_state *state)
{
	DEBUG(10, ("scavenger: %s started, parent: %s\n",
		   server_id_str(talloc_tos(), state->scavenger_id),
		   server_id_str(talloc_tos(), &state->parent_id)));

	while (true) {
		TALLOC_CTX *frame = talloc_stackframe();
		int ret;

		ret = tevent_loop_once(state->ev);
		if (ret != 0) {
			DEBUG(2, ("tevent_loop_once failed: %s\n",
				  strerror(errno)));
			TALLOC_FREE(frame);
			return 1;
		}

		DEBUG(10, ("scavenger: %s event loop iteration\n",
			   server_id_str(talloc_tos(), state->scavenger_id)));
		TALLOC_FREE(frame);
	}

	return 0;
}
Beispiel #2
0
static void smbd_scavenger_msg(struct messaging_context *msg_ctx,
			       void *private_data,
			       uint32_t msg_type,
			       struct server_id src,
			       DATA_BLOB *data)
{
	struct smbd_scavenger_state *state =
		talloc_get_type_abort(private_data,
				      struct smbd_scavenger_state);
	TALLOC_CTX *frame = talloc_stackframe();
	struct server_id self = messaging_server_id(msg_ctx);
	struct scavenger_message *msg = NULL;

	DEBUG(10, ("smbd_scavenger_msg: %s got message from %s\n",
		   server_id_str(talloc_tos(), &self),
		   server_id_str(talloc_tos(), &src)));

	if (server_id_equal(&state->parent_id, &self)) {
		NTSTATUS status;

		if (!smbd_scavenger_running(state) &&
		    !smbd_scavenger_start(state))
		{
			DEBUG(2, ("Failed to start scavenger\n"));
			goto done;
		}
		DEBUG(10, ("forwarding message to scavenger\n"));

		status = messaging_send(msg_ctx,
					*state->scavenger_id, msg_type, data);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(2, ("forwarding message to scavenger failed: "
				  "%s\n", nt_errstr(status)));
			goto done;
		}
		goto done;
	}

	if (!state->am_scavenger) {
		DEBUG(10, ("im not the scavenger: ignore message\n"));
		goto done;
	}

	if (!server_id_equal(&state->parent_id, &src)) {
		DEBUG(10, ("scavenger: ignore spurious message\n"));
		goto done;
	}

	DEBUG(10, ("scavenger: got a message\n"));
	msg = (struct scavenger_message*)data->data;
	scavenger_add_timer(state, msg);
done:
	talloc_free(frame);
}
Beispiel #3
0
static void smbd_scavenger_parent_dead(struct tevent_context *event_ctx,
				       struct tevent_fd *fde,
				       uint16_t flags, void *private_data)
{
	struct smbd_scavenger_state *state = talloc_get_type_abort(
		private_data, struct smbd_scavenger_state);

	DEBUG(2, ("scavenger: %s parent %s died\n",
		  server_id_str(talloc_tos(), state->scavenger_id),
		  server_id_str(talloc_tos(), &state->parent_id)));

	exit_server("smbd_scavenger_parent_dead");
}
Beispiel #4
0
void scavenger_schedule_disconnected(struct files_struct *fsp)
{
	NTSTATUS status;
	struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx);
	struct timeval disconnect_time, until;
	uint64_t timeout_usec;
	struct scavenger_message msg;
	DATA_BLOB msg_blob;

	if (fsp->op == NULL) {
		return;
	}
	nttime_to_timeval(&disconnect_time, fsp->op->global->disconnect_time);
	timeout_usec = 1000 * fsp->op->global->durable_timeout_msec;
	until = timeval_add(&disconnect_time,
			    timeout_usec / 1000000,
			    timeout_usec % 1000000);

	ZERO_STRUCT(msg);
	msg.file_id = fsp->file_id;
	msg.open_persistent_id = fsp->op->global->open_persistent_id;
	msg.until = timeval_to_nttime(&until);

	DEBUG(10, ("smbd: %s mark file %s as disconnected at %s with timeout "
		   "at %s in %fs\n",
		   server_id_str(talloc_tos(), &self),
		   file_id_string_tos(&fsp->file_id),
		   timeval_string(talloc_tos(), &disconnect_time, true),
		   timeval_string(talloc_tos(), &until, true),
		   fsp->op->global->durable_timeout_msec/1000.0));

	SMB_ASSERT(server_id_is_disconnected(&fsp->op->global->server_id));
	SMB_ASSERT(!server_id_equal(&self, &smbd_scavenger_state->parent_id));
	SMB_ASSERT(!smbd_scavenger_state->am_scavenger);

	msg_blob = data_blob_const(&msg, sizeof(msg));
	DEBUG(10, ("send message to scavenger\n"));

	status = messaging_send(smbd_scavenger_state->msg,
				smbd_scavenger_state->parent_id,
				MSG_SMB_SCAVENGER,
				&msg_blob);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(2, ("Failed to send message to parent smbd %s "
			  "from %s: %s\n",
			  server_id_str(talloc_tos(),
					&smbd_scavenger_state->parent_id),
			  server_id_str(talloc_tos(), &self),
			  nt_errstr(status)));
	}
}
Beispiel #5
0
static int net_serverid_list_fn(const struct server_id *id,
				uint32_t msg_flags, void *priv)
{
	char *str = server_id_str(talloc_tos(), id);
	d_printf("%s %llu 0x%x\n", str, (unsigned long long)id->unique_id,
		 (unsigned int)msg_flags);
	TALLOC_FREE(str);
	return 0;
}
Beispiel #6
0
static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
					void *private_data,
					uint32_t msg_type,
					struct server_id src,
					DATA_BLOB *data)
{
	struct file_id id;
	unsigned long file_id;
	files_struct *fsp;
	struct smbd_server_connection *sconn =
		talloc_get_type_abort(private_data,
		struct smbd_server_connection);

	if (data->data == NULL) {
		DEBUG(0, ("Got NULL buffer\n"));
		return;
	}

	if (data->length != MSG_SMB_KERNEL_BREAK_SIZE) {
		DEBUG(0, ("Got invalid msg len %d\n", (int)data->length));
		return;
	}

	/* Pull the data from the message. */
	pull_file_id_24((char *)data->data, &id);
	file_id = (unsigned long)IVAL(data->data, 24);

	DEBUG(10, ("Got kernel oplock break message from pid %s: %s/%u\n",
		   server_id_str(talloc_tos(), &src), file_id_string_tos(&id),
		   (unsigned int)file_id));

	fsp = initial_break_processing(sconn, id, file_id);

	if (fsp == NULL) {
		DEBUG(3, ("Got a kernel oplock break message for a file "
			  "I don't know about\n"));
		return;
	}

	if (fsp->sent_oplock_break != NO_BREAK_SENT) {
		/* This is ok, kernel oplocks come in completely async */
		DEBUG(3, ("Got a kernel oplock request while waiting for a "
			  "break reply\n"));
		return;
	}

	if (sconn->using_smb2) {
		send_break_message_smb2(fsp, OPLOCKLEVEL_NONE);
	} else {
		send_break_message_smb1(fsp, OPLOCKLEVEL_NONE);
	}

	fsp->sent_oplock_break = BREAK_TO_NONE_SENT;

	add_oplock_timeout_handler(fsp);
}
Beispiel #7
0
/*
 A useful function for testing the message system.
*/
static void ping_message(struct imessaging_context *msg, void *private_data,
			 uint32_t msg_type, struct server_id src, DATA_BLOB *data)
{
	char *task_id = server_id_str(NULL, &src);
	DEBUG(1,("INFO: Received PING message from server %s [%.*s]\n",
		 task_id, (int)data->length,
		 data->data?(const char *)data->data:""));
	talloc_free(task_id);
	imessaging_send(msg, src, MSG_PONG, data);
}
Beispiel #8
0
static int net_g_lock_dump_fn(struct server_id pid, enum g_lock_type lock_type,
			      void *private_data)
{
	char *pidstr;

	pidstr = server_id_str(talloc_tos(), &pid);
	d_printf("%s: %s\n", pidstr,
		 (lock_type & 1) ? "WRITE" : "READ");
	TALLOC_FREE(pidstr);
	return 0;
}
Beispiel #9
0
static void smbd_scavenger_done(struct tevent_context *event_ctx, struct tevent_fd *fde,
			        uint16_t flags, void *private_data)
{
	struct smbd_scavenger_state *state = talloc_get_type_abort(
		private_data, struct smbd_scavenger_state);

	DEBUG(2, ("scavenger: %s died\n",
		  server_id_str(talloc_tos(), state->scavenger_id)));

	TALLOC_FREE(state->scavenger_id);
}
Beispiel #10
0
static void pong_cb(struct messaging_context *msg,
		    void *private_data, 
		    uint32_t msg_type, 
		    struct server_id pid,
		    DATA_BLOB *data)
{
	char *src_string = server_id_str(NULL, &pid);
	printf("PONG from pid %s\n", src_string);
	TALLOC_FREE(src_string);
	num_replies++;
}
Beispiel #11
0
/* 
   return the path to a messaging socket
*/
static char *imessaging_path(struct imessaging_context *msg, struct server_id server_id)
{
	TALLOC_CTX *tmp_ctx = talloc_new(msg);
	const char *id = server_id_str(tmp_ctx, &server_id);
	char *s;
	if (id == NULL) {
		return NULL;
	}
	s = talloc_asprintf(msg, "%s/msg.%s", msg->base_path, id);
	talloc_steal(s, tmp_ctx);
	return s;
}
Beispiel #12
0
static void winbind_validate_cache_cb(struct messaging_context *msg,
				      void *private_data,
				      uint32_t msg_type,
				      struct server_id pid,
				      DATA_BLOB *data)
{
	char *src_string = server_id_str(NULL, &pid);
	printf("Winbindd cache is %svalid. (answer from pid %s)\n",
	       (*(data->data) == 0 ? "" : "NOT "), src_string);
	TALLOC_FREE(src_string);
	num_replies++;
}
Beispiel #13
0
static void print_pid_string_cb(struct messaging_context *msg,
				void *private_data, 
				uint32_t msg_type, 
				struct server_id pid,
				DATA_BLOB *data)
{
	char *pidstr;

	pidstr = server_id_str(talloc_tos(), &pid);
	printf("PID %s: %.*s", pidstr, (int)data->length,
	       (const char *)data->data);
	TALLOC_FREE(pidstr);
	num_replies++;
}
Beispiel #14
0
/*
  handle a socket write event
*/
static void imessaging_send_handler(struct imessaging_context *msg)
{
	while (msg->pending) {
		struct imessaging_rec *rec = msg->pending;
		NTSTATUS status;
		status = try_send(rec);
		if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
			rec->retries++;
			if (rec->retries > 3) {
				/* we're getting continuous write errors -
				   backoff this record */
				DLIST_REMOVE(msg->pending, rec);
				DLIST_ADD_END(msg->retry_queue, rec, 
					      struct imessaging_rec *);
				if (msg->retry_te == NULL) {
					msg->retry_te = 
						tevent_add_timer(msg->event.ev, msg,
								timeval_current_ofs(1, 0), 
								msg_retry_timer, msg);
				}
			}
			break;
		}
		rec->retries = 0;
		if (!NT_STATUS_IS_OK(status)) {
			TALLOC_CTX *tmp_ctx = talloc_new(msg);
			DEBUG(1,("messaging: Lost message from %s to %s of type %u - %s\n", 
				 server_id_str(tmp_ctx, &rec->header->from),
				 server_id_str(tmp_ctx, &rec->header->to),
				 rec->header->msg_type, 
				 nt_errstr(status)));
			talloc_free(tmp_ctx);
		}
		DLIST_REMOVE(msg->pending, rec);
		talloc_free(rec);
	}
Beispiel #15
0
/*
  make a IRPC call to the drepl task to ask it to get the RID
  Manager to give us another RID pool.

  This function just sends the message to the drepl task then
  returns immediately. It should be called well before we
  completely run out of RIDs
 */
static int ridalloc_poke_rid_manager(struct ldb_module *module)
{
	struct imessaging_context *msg;
	struct server_id *server;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct loadparm_context *lp_ctx =
		(struct loadparm_context *)ldb_get_opaque(ldb, "loadparm");
	TALLOC_CTX *tmp_ctx = talloc_new(module);
	NTSTATUS status;

	msg = imessaging_client_init(tmp_ctx, lp_ctx,
				    ldb_get_event_context(ldb));
	if (!msg) {
		ldb_asprintf_errstring(ldb_module_get_ctx(module),
				"Failed to send MSG_DREPL_ALLOCATE_RID, "
				"unable init client messaging context");
		DEBUG(3,(__location__ ": Failed to create messaging context\n"));
		talloc_free(tmp_ctx);
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}

	server = irpc_servers_byname(msg, msg, "dreplsrv");
	if (!server) {
		ldb_asprintf_errstring(ldb_module_get_ctx(module),
				"Failed to send MSG_DREPL_ALLOCATE_RID, "
				"unable to locate dreplsrv");
		/* this means the drepl service is not running */
		talloc_free(tmp_ctx);
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}

	status = imessaging_send(msg, server[0], MSG_DREPL_ALLOCATE_RID, NULL);

	/* Only error out if an error happened, not on STATUS_MORE_ENTRIES, ie a delayed message */
	if (NT_STATUS_IS_ERR(status)) {
		ldb_asprintf_errstring(ldb_module_get_ctx(module),
				"Failed to send MSG_DREPL_ALLOCATE_RID to dreplsrv at %s: %s",
				server_id_str(tmp_ctx, server), nt_errstr(status));
		talloc_free(tmp_ctx);
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}

	talloc_free(tmp_ctx);
	return LDB_SUCCESS;
}
Beispiel #16
0
static int net_serverid_wipe_fn(struct db_record *rec,
				const struct server_id *id,
				uint32_t msg_flags, void *private_data)
{
	NTSTATUS status;

	if (id->vnn != get_my_vnn()) {
		return 0;
	}
	status = dbwrap_record_delete(rec);
	if (!NT_STATUS_IS_OK(status)) {
		char *str = server_id_str(talloc_tos(), id);
		DEBUG(1, ("Could not delete serverid.tdb record %s: %s\n",
			  str, nt_errstr(status)));
		TALLOC_FREE(str);
	}
	return 0;
}
Beispiel #17
0
static bool scavenger_wait_hello(int fd, struct server_id *child)
{
	uint8_t *msg = (uint8_t *)child;
	size_t remaining = sizeof(*child);
	size_t ofs = 0;

	while (remaining > 0) {
		ssize_t ret;

		ret = sys_read(fd, msg + ofs, remaining);
		if (ret == -1) {
			DEBUG(2, ("Failed to read from pipe: %s\n",
				  strerror(errno)));
			return false;
		}
		remaining -= ret;
	}

	DEBUG(4, ("scavenger_say_hello: child[%s]\n",
		  server_id_str(talloc_tos(), child)));
	return true;
}
Beispiel #18
0
static bool scavenger_say_hello(int fd, struct server_id self)
{
	const uint8_t *msg = (const uint8_t *)&self;
	size_t remaining = sizeof(self);
	size_t ofs = 0;

	while (remaining > 0) {
		ssize_t ret;

		ret = sys_write(fd, msg + ofs, remaining);
		if (ret == -1) {
			DEBUG(2, ("Failed to write to pipe: %s\n",
				  strerror(errno)));
			return false;
		}
		remaining -= ret;
	}

	DEBUG(4, ("scavenger_say_hello: self[%s]\n",
		  server_id_str(talloc_tos(), &self)));
	return true;
}
Beispiel #19
0
NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id)
{
    NTSTATUS status = NT_STATUS_OK;
    TALLOC_CTX *frame = talloc_stackframe();
    struct smbXsrv_open_global0 *op = NULL;
    uint8_t key_buf[SMBXSRV_OPEN_GLOBAL_TDB_KEY_SIZE];
    TDB_DATA key;
    TDB_DATA val;
    struct db_record *rec;
    bool delete_open = false;
    uint32_t global_id = persistent_id & UINT32_MAX;

    key = smbXsrv_open_global_id_to_key(global_id, key_buf);
    rec = dbwrap_fetch_locked(smbXsrv_open_global_db_ctx, frame, key);
    if (rec == NULL) {
        status = NT_STATUS_NOT_FOUND;
        DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] "
                  "failed to fetch record from %s - %s\n",
                  global_id, dbwrap_name(smbXsrv_open_global_db_ctx),
                  nt_errstr(status)));
        goto done;
    }

    val = dbwrap_record_get_value(rec);
    if (val.dsize == 0) {
        DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] "
                   "empty record in %s, skipping...\n",
                   global_id, dbwrap_name(smbXsrv_open_global_db_ctx)));
        goto done;
    }

    status = smbXsrv_open_global_parse_record(talloc_tos(), rec, &op);
    if (!NT_STATUS_IS_OK(status)) {
        DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] "
                  "failed to read record: %s\n",
                  global_id, nt_errstr(status)));
        goto done;
    }

    if (server_id_is_disconnected(&op->server_id)) {
        struct timeval now, disconnect_time;
        int64_t tdiff;
        now = timeval_current();
        nttime_to_timeval(&disconnect_time, op->disconnect_time);
        tdiff = usec_time_diff(&now, &disconnect_time);
        delete_open = (tdiff >= 1000*op->durable_timeout_msec);

        DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] "
                   "disconnected at [%s] %us ago with "
                   "timeout of %us -%s reached\n",
                   global_id,
                   nt_time_string(frame, op->disconnect_time),
                   (unsigned)(tdiff/1000000),
                   op->durable_timeout_msec / 1000,
                   delete_open ? "" : " not"));
    } else if (!serverid_exists(&op->server_id)) {
        DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] "
                   "server[%s] does not exist\n",
                   global_id, server_id_str(frame, &op->server_id)));
        delete_open = true;
    }

    if (!delete_open) {
        goto done;
    }

    status = dbwrap_record_delete(rec);
    if (!NT_STATUS_IS_OK(status)) {
        DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] "
                  "failed to delete record"
                  "from %s: %s\n", global_id,
                  dbwrap_name(smbXsrv_open_global_db_ctx),
                  nt_errstr(status)));
        goto done;
    }

    DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] "
               "delete record from %s\n",
               global_id,
               dbwrap_name(smbXsrv_open_global_db_ctx)));

done:
    talloc_free(frame);
    return status;
}
Beispiel #20
0
static void process_oplock_break_message(struct messaging_context *msg_ctx,
					 void *private_data,
					 uint32_t msg_type,
					 struct server_id src,
					 DATA_BLOB *data)
{
	struct share_mode_entry msg;
	files_struct *fsp;
	bool break_to_level2 = False;
	bool use_kernel;
	struct smbd_server_connection *sconn =
		talloc_get_type_abort(private_data,
		struct smbd_server_connection);
	struct server_id self = messaging_server_id(sconn->msg_ctx);
	struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
	uint16_t break_to;

	if (data->data == NULL) {
		DEBUG(0, ("Got NULL buffer\n"));
		return;
	}

	if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
		DEBUG(0, ("Got invalid msg len %d\n", (int)data->length));
		return;
	}

	/* De-linearize incoming message. */
	message_to_share_mode_entry(&msg, (char *)data->data);
	break_to = msg.op_type;

	DEBUG(10, ("Got oplock break to %u message from pid %s: %s/%llu\n",
		   (unsigned)break_to, server_id_str(talloc_tos(), &src),
		   file_id_string_tos(&msg.id),
		   (unsigned long long)msg.share_file_id));

	fsp = initial_break_processing(sconn, msg.id, msg.share_file_id);

	if (fsp == NULL) {
		/* We hit a race here. Break messages are sent, and before we
		 * get to process this message, we have closed the file. */
		DEBUG(3, ("Did not find fsp\n"));
		return;
	}

	if (fsp->sent_oplock_break != NO_BREAK_SENT) {
		/*
		 * Nothing to do anymore
		 */
		return;
	}

	if (break_to == fsp->oplock_type) {
		DEBUG(3, ("Already downgraded oplock on %s: %s\n",
			  file_id_string_tos(&fsp->file_id),
			  fsp_str_dbg(fsp)));
		return;
	}

	use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) && koplocks;

	if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) &&
	    (break_to != NO_OPLOCK) &&
	    !(use_kernel && !(koplocks->flags & KOPLOCKS_LEVEL2_SUPPORTED)) &&
	    lp_level2_oplocks(SNUM(fsp->conn))) {
		break_to_level2 = True;
	}

	/* Need to wait before sending a break
	   message if we sent ourselves this message. */
	if (serverid_equal(&self, &src)) {
		wait_before_sending_break();
	}

	if (sconn->using_smb2) {
		send_break_message_smb2(fsp, break_to_level2 ?
			OPLOCKLEVEL_II : OPLOCKLEVEL_NONE);
	} else {
		send_break_message_smb1(fsp, break_to_level2 ?
			OPLOCKLEVEL_II : OPLOCKLEVEL_NONE);
	}

	if ((fsp->oplock_type == LEVEL_II_OPLOCK) && (break_to == NO_OPLOCK)) {
		/*
		 * This is an async break without a reply and thus no timeout
		 */
		remove_oplock(fsp);
		return;
	}
	fsp->sent_oplock_break = break_to_level2 ? LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
	add_oplock_timeout_handler(fsp);
}
Beispiel #21
0
static void smbXsrv_tcon_global_verify_record(struct db_record *db_rec,
					bool *is_free,
					bool *was_free,
					TALLOC_CTX *mem_ctx,
					struct smbXsrv_tcon_global0 **_g)
{
	TDB_DATA key;
	TDB_DATA val;
	DATA_BLOB blob;
	struct smbXsrv_tcon_globalB global_blob;
	enum ndr_err_code ndr_err;
	struct smbXsrv_tcon_global0 *global = NULL;
	bool exists;
	TALLOC_CTX *frame = talloc_stackframe();

	*is_free = false;

	if (was_free) {
		*was_free = false;
	}
	if (_g) {
		*_g = NULL;
	}

	key = dbwrap_record_get_key(db_rec);

	val = dbwrap_record_get_value(db_rec);
	if (val.dsize == 0) {
		TALLOC_FREE(frame);
		*is_free = true;
		if (was_free) {
			*was_free = true;
		}
		return;
	}

	blob = data_blob_const(val.dptr, val.dsize);

	ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
			(ndr_pull_flags_fn_t)ndr_pull_smbXsrv_tcon_globalB);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(1,("smbXsrv_tcon_global_verify_record: "
			 "key '%s' ndr_pull_struct_blob - %s\n",
			 hex_encode_talloc(frame, key.dptr, key.dsize),
			 nt_errstr(status)));
		TALLOC_FREE(frame);
		return;
	}

	DEBUG(10,("smbXsrv_tcon_global_verify_record\n"));
	if (DEBUGLVL(10)) {
		NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob);
	}

	if (global_blob.version != SMBXSRV_VERSION_0) {
		DEBUG(0,("smbXsrv_tcon_global_verify_record: "
			 "key '%s' use unsupported version %u\n",
			 hex_encode_talloc(frame, key.dptr, key.dsize),
			 global_blob.version));
		NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob);
		TALLOC_FREE(frame);
		return;
	}

	global = global_blob.info.info0;

	exists = serverid_exists(&global->server_id);
	if (!exists) {
		DEBUG(2,("smbXsrv_tcon_global_verify_record: "
			 "key '%s' server_id %s does not exist.\n",
			 hex_encode_talloc(frame, key.dptr, key.dsize),
			 server_id_str(frame, &global->server_id)));
		if (DEBUGLVL(2)) {
			NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob);
		}
		TALLOC_FREE(frame);
		dbwrap_record_delete(db_rec);
		*is_free = true;
		return;
	}

	if (_g) {
		*_g = talloc_move(mem_ctx, &global);
	}
	TALLOC_FREE(frame);
}
Beispiel #22
0
static bool smbd_scavenger_start(struct smbd_scavenger_state *state)
{
	struct server_id self = messaging_server_id(state->msg);
	struct tevent_fd *fde = NULL;
	int fds[2];
	int ret;
	uint64_t unique_id;
	bool ok;

	SMB_ASSERT(server_id_equal(&state->parent_id, &self));

	if (smbd_scavenger_running(state)) {
		DEBUG(10, ("scavenger %s already running\n",
			   server_id_str(talloc_tos(),
					 state->scavenger_id)));
		return true;
	}

	if (state->scavenger_id != NULL) {
		DEBUG(10, ("scavenger zombie %s, cleaning up\n",
			   server_id_str(talloc_tos(),
					 state->scavenger_id)));
		TALLOC_FREE(state->scavenger_id);
	}

	state->scavenger_id = talloc_zero(state, struct server_id);
	if (state->scavenger_id == NULL) {
		DEBUG(2, ("Out of memory\n"));
		goto fail;
	}
	talloc_set_destructor(state->scavenger_id,
			      smbd_scavenger_server_id_destructor);

	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
	if (ret == -1) {
		DEBUG(2, ("socketpair failed: %s", strerror(errno)));
		goto fail;
	}

	smb_set_close_on_exec(fds[0]);
	smb_set_close_on_exec(fds[1]);

	unique_id = serverid_get_random_unique_id();

	ret = fork();
	if (ret == -1) {
		int err = errno;
		close(fds[0]);
		close(fds[1]);
		DEBUG(0, ("fork failed: %s", strerror(err)));
		goto fail;
	}

	if (ret == 0) {
		/* child */

		NTSTATUS status;

		close(fds[0]);

		am_parent = NULL;

		set_my_unique_id(unique_id);

		status = reinit_after_fork(state->msg, state->ev, true);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(2, ("reinit_after_fork failed: %s\n",
				  nt_errstr(status)));
			exit_server("reinit_after_fork failed");
			return false;
		}

		prctl_set_comment("smbd-scavenger");

		state->am_scavenger = true;
		*state->scavenger_id = messaging_server_id(state->msg);

		scavenger_setup_sig_term_handler(state->ev);

		serverid_register(*state->scavenger_id, FLAG_MSG_GENERAL);

		ok = scavenger_say_hello(fds[1], *state->scavenger_id);
		if (!ok) {
			DEBUG(2, ("scavenger_say_hello failed\n"));
			exit_server("scavenger_say_hello failed");
			return false;
		}

		fde = tevent_add_fd(state->ev, state->scavenger_id,
				    fds[1], TEVENT_FD_READ,
				    smbd_scavenger_parent_dead, state);
		if (fde == NULL) {
			DEBUG(2, ("tevent_add_fd(smbd_scavenger_parent_dead) "
				  "failed\n"));
			exit_server("tevent_add_fd(smbd_scavenger_parent_dead) "
				    "failed");
			return false;
		}
		tevent_fd_set_auto_close(fde);

		ret = smbd_scavenger_main(state);

		DEBUG(10, ("scavenger ended: %d\n", ret));
		exit_server_cleanly("scavenger ended");
		return false;
	}

	/* parent */
	close(fds[1]);

	ok = scavenger_wait_hello(fds[0], state->scavenger_id);
	if (!ok) {
		close(fds[0]);
		goto fail;
	}

	fde = tevent_add_fd(state->ev, state->scavenger_id,
			    fds[0], TEVENT_FD_READ,
			    smbd_scavenger_done, state);
	if (fde == NULL) {
		close(fds[0]);
		goto fail;
	}
	tevent_fd_set_auto_close(fde);

	return true;
fail:
	TALLOC_FREE(state->scavenger_id);
	return false;
}
Beispiel #23
0
/*
  called when a new socket connection has been established. This is called in the process
  context of the new process (if appropriate)
*/
static void stream_new_connection(struct tevent_context *ev,
				  struct loadparm_context *lp_ctx,
				  struct socket_context *sock, 
				  struct server_id server_id, void *private_data)
{
	struct stream_socket *stream_socket = talloc_get_type(private_data, struct stream_socket);
	struct stream_connection *srv_conn;

	srv_conn = talloc_zero(ev, struct stream_connection);
	if (!srv_conn) {
		DEBUG(0,("talloc(mem_ctx, struct stream_connection) failed\n"));
		return;
	}

	talloc_steal(srv_conn, sock);

	srv_conn->private_data	= stream_socket->private_data;
	srv_conn->model_ops     = stream_socket->model_ops;
	srv_conn->socket	= sock;
	srv_conn->server_id	= server_id;
	srv_conn->ops           = stream_socket->ops;
	srv_conn->event.ctx	= ev;
	srv_conn->lp_ctx	= lp_ctx;

	if (!socket_check_access(sock, "smbd", lpcfg_hostsallow(NULL, lpcfg_default_service(lp_ctx)), lpcfg_hostsdeny(NULL, lpcfg_default_service(lp_ctx)))) {
		stream_terminate_connection(srv_conn, "denied by access rules");
		return;
	}

	srv_conn->event.fde	= tevent_add_fd(ev, srv_conn, socket_get_fd(sock),
						0, stream_io_handler_fde, srv_conn);
	if (!srv_conn->event.fde) {
		stream_terminate_connection(srv_conn, "tevent_add_fd() failed");
		return;
	}

	/* setup to receive internal messages on this connection */
	srv_conn->msg_ctx = imessaging_init(srv_conn,
					    lpcfg_imessaging_path(srv_conn, lp_ctx),
					    srv_conn->server_id, ev, false);
	if (!srv_conn->msg_ctx) {
		stream_terminate_connection(srv_conn, "imessaging_init() failed");
		return;
	}

	srv_conn->remote_address = socket_get_remote_addr(srv_conn->socket, srv_conn);
	if (!srv_conn->remote_address) {
		stream_terminate_connection(srv_conn, "socket_get_remote_addr() failed");
		return;
	}

	srv_conn->local_address = socket_get_local_addr(srv_conn->socket, srv_conn);
	if (!srv_conn->local_address) {
		stream_terminate_connection(srv_conn, "socket_get_local_addr() failed");
		return;
	}

	{
		TALLOC_CTX *tmp_ctx;
		const char *title;

		tmp_ctx = talloc_new(srv_conn);

		title = talloc_asprintf(tmp_ctx, "conn[%s] c[%s] s[%s] server_id[%s]",
					stream_socket->ops->name, 
					tsocket_address_string(srv_conn->remote_address, tmp_ctx),
					tsocket_address_string(srv_conn->local_address, tmp_ctx),
					server_id_str(tmp_ctx, &server_id));
		if (title) {
			stream_connection_set_title(srv_conn, title);
		}
		talloc_free(tmp_ctx);
	}

	/* we're now ready to start receiving events on this stream */
	TEVENT_FD_READABLE(srv_conn->event.fde);

	/* call the server specific accept code */
	stream_socket->ops->accept_connection(srv_conn);
}