#include "lib/util/tevent_unix.h"
#include "lib/background.h"
#include "lib/messages_dgm.h"
-#include "lib/iov_buf.h"
+#include "lib/util/iov_buf.h"
#include "lib/util/server_id_db.h"
#include "lib/messages_dgm_ref.h"
+#include "lib/messages_util.h"
struct messaging_callback {
struct messaging_callback *prev, *next;
- uint32 msg_type;
+ uint32_t msg_type;
void (*fn)(struct messaging_context *msg, void *private_data,
uint32_t msg_type,
struct server_id server_id, DATA_BLOB *data);
struct server_id_db *names_db;
};
-struct messaging_hdr {
- uint32_t msg_type;
- struct server_id dst;
- struct server_id src;
-};
+static void messaging_dispatch_rec(struct messaging_context *msg_ctx,
+ struct messaging_rec *rec);
/****************************************************************************
A useful function for testing the message system.
messaging_send(msg_ctx, src, MSG_PONG, data);
}
-/****************************************************************************
- Register/replace a dispatch function for a particular message type.
- JRA changed Dec 13 2006. Only one message handler now permitted per type.
- *NOTE*: Dispatch functions must be able to cope with incoming
- messages on an *odd* byte boundary.
-****************************************************************************/
-
-struct msg_all {
- struct messaging_context *msg_ctx;
- int msg_type;
- uint32 msg_flag;
- const void *buf;
- size_t len;
- int n_sent;
-};
-
-/****************************************************************************
- Send one of the messages for the broadcast.
-****************************************************************************/
-
-static int traverse_fn(struct db_record *rec, const struct server_id *id,
- uint32_t msg_flags, void *state)
-{
- struct msg_all *msg_all = (struct msg_all *)state;
- NTSTATUS status;
-
- /* Don't send if the receiver hasn't registered an interest. */
-
- if((msg_flags & msg_all->msg_flag) == 0) {
- return 0;
- }
-
- /* If the msg send fails because the pid was not found (i.e. smbd died),
- * the msg has already been deleted from the messages.tdb.*/
-
- status = messaging_send_buf(msg_all->msg_ctx, *id, msg_all->msg_type,
- (const uint8_t *)msg_all->buf, msg_all->len);
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
- struct server_id_buf idbuf;
-
- /*
- * If the pid was not found delete the entry from
- * serverid.tdb
- */
-
- DEBUG(2, ("pid %s doesn't exist\n",
- server_id_str_buf(*id, &idbuf)));
-
- dbwrap_record_delete(rec);
- }
- msg_all->n_sent++;
- return 0;
-}
-
-/**
- * Send a message to all smbd processes.
- *
- * It isn't very efficient, but should be OK for the sorts of
- * applications that use it. When we need efficient broadcast we can add
- * it.
- *
- * @param n_sent Set to the number of messages sent. This should be
- * equal to the number of processes, but be careful for races.
- *
- * @retval True for success.
- **/
-bool message_send_all(struct messaging_context *msg_ctx,
- int msg_type,
- const void *buf, size_t len,
- int *n_sent)
-{
- struct msg_all msg_all;
-
- msg_all.msg_type = msg_type;
- if (msg_type < 0x100) {
- msg_all.msg_flag = FLAG_MSG_GENERAL;
- } else if (msg_type > 0x100 && msg_type < 0x200) {
- msg_all.msg_flag = FLAG_MSG_NMBD;
- } else if (msg_type > 0x200 && msg_type < 0x300) {
- msg_all.msg_flag = FLAG_MSG_PRINT_GENERAL;
- } else if (msg_type > 0x300 && msg_type < 0x400) {
- msg_all.msg_flag = FLAG_MSG_SMBD;
- } else if (msg_type > 0x400 && msg_type < 0x600) {
- msg_all.msg_flag = FLAG_MSG_WINBIND;
- } else if (msg_type > 4000 && msg_type < 5000) {
- msg_all.msg_flag = FLAG_MSG_DBWRAP;
- } else {
- return false;
- }
-
- msg_all.buf = buf;
- msg_all.len = len;
- msg_all.n_sent = 0;
- msg_all.msg_ctx = msg_ctx;
-
- serverid_traverse(traverse_fn, &msg_all);
- if (n_sent)
- *n_sent = msg_all.n_sent;
- return true;
-}
-
static void messaging_recv_cb(const uint8_t *msg, size_t msg_len,
int *fds, size_t num_fds,
void *private_data)
{
struct messaging_context *msg_ctx = talloc_get_type_abort(
private_data, struct messaging_context);
- const struct messaging_hdr *hdr;
struct server_id_buf idbuf;
struct messaging_rec rec;
int64_t fds64[MIN(num_fds, INT8_MAX)];
size_t i;
- if (msg_len < sizeof(*hdr)) {
- for (i=0; i < num_fds; i++) {
- close(fds[i]);
- }
- DEBUG(1, ("message too short: %u\n", (unsigned)msg_len));
- return;
+ if (msg_len < MESSAGE_HDR_LENGTH) {
+ DBG_WARNING("message too short: %zu\n", msg_len);
+ goto close_fail;
}
if (num_fds > INT8_MAX) {
- for (i=0; i < num_fds; i++) {
- close(fds[i]);
- }
- DEBUG(1, ("too many fds: %u\n", (unsigned)num_fds));
- return;
+ DBG_WARNING("too many fds: %zu\n", num_fds);
+ goto close_fail;
}
/*
fds[i] = -1;
}
- /*
- * messages_dgm guarantees alignment, so we can cast here
- */
- hdr = (const struct messaging_hdr *)msg;
-
- DEBUG(10, ("%s: Received message 0x%x len %u (num_fds:%u) from %s\n",
- __func__, (unsigned)hdr->msg_type,
- (unsigned)(msg_len - sizeof(*hdr)),
- (unsigned)num_fds,
- server_id_str_buf(hdr->src, &idbuf)));
-
rec = (struct messaging_rec) {
.msg_version = MESSAGE_VERSION,
- .msg_type = hdr->msg_type,
- .src = hdr->src,
- .dest = hdr->dst,
- .buf.data = discard_const_p(uint8, msg) + sizeof(*hdr),
- .buf.length = msg_len - sizeof(*hdr),
+ .buf.data = discard_const_p(uint8_t, msg) + MESSAGE_HDR_LENGTH,
+ .buf.length = msg_len - MESSAGE_HDR_LENGTH,
.num_fds = num_fds,
.fds = fds64,
};
+ message_hdr_get(&rec.msg_type, &rec.src, &rec.dest, msg);
+
+ DBG_DEBUG("Received message 0x%x len %zu (num_fds:%zu) from %s\n",
+ (unsigned)rec.msg_type, rec.buf.length, num_fds,
+ server_id_str_buf(rec.src, &idbuf));
+
messaging_dispatch_rec(msg_ctx, &rec);
+ return;
+
+close_fail:
+ for (i=0; i < num_fds; i++) {
+ close(fds[i]);
+ }
}
static int messaging_context_destructor(struct messaging_context *ctx)
{
unsigned i;
- messaging_dgm_destroy();
-
for (i=0; i<ctx->num_new_waiters; i++) {
if (ctx->new_waiters[i] != NULL) {
tevent_req_set_cleanup_fn(ctx->new_waiters[i], NULL);
struct tevent_context *ev)
{
struct messaging_context *ctx;
- NTSTATUS status;
int ret;
const char *lck_path;
const char *priv_path;
return NULL;
}
- ctx->id = procid_self();
+ ctx->id = (struct server_id) {
+ .pid = getpid(), .vnn = NONCLUSTER_VNN
+ };
+
ctx->event_ctx = ev;
sec_init();
- lck_path = lock_path("msg");
+ lck_path = lock_path("msg.lock");
if (lck_path == NULL) {
TALLOC_FREE(ctx);
return NULL;
return NULL;
}
- priv_path = private_path("sock");
+ priv_path = private_path("msg.sock");
+ if (priv_path == NULL) {
+ TALLOC_FREE(ctx);
+ return NULL;
+ }
ok = directory_create_or_exist_strict(priv_path, sec_initial_uid(),
0700);
}
ctx->msg_dgm_ref = messaging_dgm_ref(
- ctx, ctx->event_ctx, ctx->id.unique_id,
+ ctx, ctx->event_ctx, &ctx->id.unique_id,
priv_path, lck_path, messaging_recv_cb, ctx, &ret);
if (ctx->msg_dgm_ref == NULL) {
return NULL;
}
- ctx->names_db = server_id_db_init(
- ctx, ctx->id, lp_cache_directory(), 0,
- TDB_INCOMPATIBLE_HASH|TDB_CLEAR_IF_FIRST);
- if (ctx->names_db == NULL) {
- DEBUG(10, ("%s: server_id_db_init failed\n", __func__));
- TALLOC_FREE(ctx);
- return NULL;
- }
-
talloc_set_destructor(ctx, messaging_context_destructor);
if (lp_clustering()) {
- status = messaging_ctdbd_init(ctx, ctx, &ctx->remote);
+ ret = messaging_ctdbd_init(ctx, ctx, &ctx->remote);
- if (!NT_STATUS_IS_OK(status)) {
+ if (ret != 0) {
DEBUG(2, ("messaging_ctdbd_init failed: %s\n",
- nt_errstr(status)));
+ strerror(ret)));
TALLOC_FREE(ctx);
return NULL;
}
}
ctx->id.vnn = get_my_vnn();
+ ctx->names_db = server_id_db_init(
+ ctx, ctx->id, lp_lock_directory(), 0,
+ TDB_INCOMPATIBLE_HASH|TDB_CLEAR_IF_FIRST);
+ if (ctx->names_db == NULL) {
+ DEBUG(10, ("%s: server_id_db_init failed\n", __func__));
+ TALLOC_FREE(ctx);
+ return NULL;
+ }
+
messaging_register(ctx, NULL, MSG_PING, ping_message);
/* Register some debugging related messages */
register_dmalloc_msgs(ctx);
debug_register_msgs(ctx);
+ {
+ struct server_id_buf tmp;
+ DBG_DEBUG("my id: %s\n", server_id_str_buf(ctx->id, &tmp));
+ }
+
return ctx;
}
*/
NTSTATUS messaging_reinit(struct messaging_context *msg_ctx)
{
- NTSTATUS status;
int ret;
+ char *lck_path;
TALLOC_FREE(msg_ctx->msg_dgm_ref);
- msg_ctx->id = procid_self();
+ msg_ctx->id = (struct server_id) {
+ .pid = getpid(), .vnn = msg_ctx->id.vnn
+ };
+
+ lck_path = lock_path("msg.lock");
+ if (lck_path == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
msg_ctx->msg_dgm_ref = messaging_dgm_ref(
- msg_ctx, msg_ctx->event_ctx, msg_ctx->id.unique_id,
- private_path("sock"), lock_path("msg"),
+ msg_ctx, msg_ctx->event_ctx, &msg_ctx->id.unique_id,
+ private_path("msg.sock"), lck_path,
messaging_recv_cb, msg_ctx, &ret);
if (msg_ctx->msg_dgm_ref == NULL) {
return map_nt_error_from_unix(ret);
}
- TALLOC_FREE(msg_ctx->remote);
-
if (lp_clustering()) {
- status = messaging_ctdbd_init(msg_ctx, msg_ctx,
- &msg_ctx->remote);
+ ret = messaging_ctdbd_reinit(msg_ctx, msg_ctx,
+ msg_ctx->remote);
- if (!NT_STATUS_IS_OK(status)) {
+ if (ret != 0) {
DEBUG(1, ("messaging_ctdbd_init failed: %s\n",
- nt_errstr(status)));
- return status;
+ strerror(ret)));
+ return map_nt_error_from_unix(ret);
}
}
struct server_id server, uint32_t msg_type,
const DATA_BLOB *data)
{
- struct iovec iov;
+ struct iovec iov = {0};
- iov.iov_base = data->data;
- iov.iov_len = data->length;
+ if (data != NULL) {
+ iov.iov_base = data->data;
+ iov.iov_len = data->length;
+ };
return messaging_send_iov(msg_ctx, server, msg_type, &iov, 1, NULL, 0);
}
return messaging_send(msg_ctx, server, msg_type, &blob);
}
-NTSTATUS messaging_send_iov_from(struct messaging_context *msg_ctx,
- struct server_id src, struct server_id dst,
- uint32_t msg_type,
- const struct iovec *iov, int iovlen,
- const int *fds, size_t num_fds)
+int messaging_send_iov_from(struct messaging_context *msg_ctx,
+ struct server_id src, struct server_id dst,
+ uint32_t msg_type,
+ const struct iovec *iov, int iovlen,
+ const int *fds, size_t num_fds)
{
int ret;
- struct messaging_hdr hdr;
+ uint8_t hdr[MESSAGE_HDR_LENGTH];
struct iovec iov2[iovlen+1];
if (server_id_is_disconnected(&dst)) {
- return NT_STATUS_INVALID_PARAMETER_MIX;
+ return EINVAL;
}
if (num_fds > INT8_MAX) {
- return NT_STATUS_INVALID_PARAMETER_MIX;
+ return EINVAL;
}
- if (!procid_is_local(&dst)) {
+ if (dst.vnn != msg_ctx->id.vnn) {
if (num_fds > 0) {
- return NT_STATUS_NOT_SUPPORTED;
+ return ENOSYS;
}
ret = msg_ctx->remote->send_fn(src, dst,
msg_type, iov, iovlen,
NULL, 0,
msg_ctx->remote);
- if (ret != 0) {
- return map_nt_error_from_unix(ret);
- }
- return NT_STATUS_OK;
+ return ret;
}
- ZERO_STRUCT(hdr);
- hdr = (struct messaging_hdr) {
- .msg_type = msg_type,
- .dst = dst,
- .src = src
- };
- iov2[0] = (struct iovec){ .iov_base = &hdr, .iov_len = sizeof(hdr) };
+ message_hdr_put(hdr, msg_type, src, dst);
+ iov2[0] = (struct iovec){ .iov_base = hdr, .iov_len = sizeof(hdr) };
memcpy(&iov2[1], iov, iovlen * sizeof(*iov));
- become_root();
ret = messaging_dgm_send(dst.pid, iov2, iovlen+1, fds, num_fds);
- unbecome_root();
- if (ret != 0) {
- return map_nt_error_from_unix(ret);
+ if (ret == EACCES) {
+ become_root();
+ ret = messaging_dgm_send(dst.pid, iov2, iovlen+1,
+ fds, num_fds);
+ unbecome_root();
}
- return NT_STATUS_OK;
+
+ return ret;
}
NTSTATUS messaging_send_iov(struct messaging_context *msg_ctx,
const struct iovec *iov, int iovlen,
const int *fds, size_t num_fds)
{
- return messaging_send_iov_from(msg_ctx, msg_ctx->id, dst, msg_type,
- iov, iovlen, fds, num_fds);
+ int ret;
+
+ ret = messaging_send_iov_from(msg_ctx, msg_ctx->id, dst, msg_type,
+ iov, iovlen, fds, num_fds);
+ if (ret != 0) {
+ return map_nt_error_from_unix(ret);
+ }
+ return NT_STATUS_OK;
}
static struct messaging_rec *messaging_rec_dup(TALLOC_CTX *mem_ctx,
state->tevent_handle = messaging_dgm_register_tevent_context(
state, ev);
- if (tevent_req_nomem(state, req)) {
+ if (tevent_req_nomem(state->tevent_handle, req)) {
return tevent_req_post(req, ev);
}
tevent_req_received(req);
return err;
}
- *presult = talloc_move(mem_ctx, &state->rec);
+ if (presult != NULL) {
+ *presult = talloc_move(mem_ctx, &state->rec);
+ }
return 0;
}
/*
Dispatch one messaging_rec
*/
-void messaging_dispatch_rec(struct messaging_context *msg_ctx,
- struct messaging_rec *rec)
+static void messaging_dispatch_rec(struct messaging_context *msg_ctx,
+ struct messaging_rec *rec)
{
struct messaging_callback *cb, *next;
unsigned i;
mess_parent_dgm_cleanup, msg);
if (req == NULL) {
DEBUG(1, ("background_job_send failed\n"));
+ return;
}
tevent_req_set_callback(req, mess_parent_dgm_cleanup_done, msg);
}