LCOV - code coverage report
Current view: top level - source4/lib/messaging - messaging.c (source / functions) Hit Total Coverage
Test: coverage report for master 469b22b8 Lines: 486 659 73.7 %
Date: 2024-06-10 12:05:21 Functions: 40 47 85.1 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Samba internal messaging functions
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2004
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "lib/events/events.h"
      24             : #include "lib/util/server_id.h"
      25             : #include "system/filesys.h"
      26             : #include "messaging/messaging.h"
      27             : #include "messaging/messaging_internal.h"
      28             : #include "../lib/util/dlinklist.h"
      29             : #include "lib/socket/socket.h"
      30             : #include "librpc/gen_ndr/ndr_irpc.h"
      31             : #include "lib/messaging/irpc.h"
      32             : #include "../lib/util/unix_privs.h"
      33             : #include "librpc/rpc/dcerpc.h"
      34             : #include "cluster/cluster.h"
      35             : #include "../lib/util/tevent_ntstatus.h"
      36             : #include "lib/param/param.h"
      37             : #include "lib/util/server_id_db.h"
      38             : #include "lib/util/talloc_report_printf.h"
      39             : #include "lib/messaging/messages_dgm.h"
      40             : #include "lib/messaging/messages_dgm_ref.h"
      41             : #include "../source3/lib/messages_util.h"
      42             : #include <tdb.h>
      43             : #include "lib/util/idtree.h"
      44             : 
      45             : /* change the message version with any incompatible changes in the protocol */
      46             : #define IMESSAGING_VERSION 1
      47             : 
      48             : /*
      49             :   a pending irpc call
      50             : */
      51             : struct irpc_request {
      52             :         struct irpc_request *prev, *next;
      53             :         struct imessaging_context *msg_ctx;
      54             :         int callid;
      55             :         struct {
      56             :                 void (*handler)(struct irpc_request *irpc, struct irpc_message *m);
      57             :                 void *private_data;
      58             :         } incoming;
      59             : };
      60             : 
      61             : /* we have a linked list of dispatch handlers for each msg_type that
      62             :    this messaging server can deal with */
      63             : struct dispatch_fn {
      64             :         struct dispatch_fn *next, *prev;
      65             :         uint32_t msg_type;
      66             :         void *private_data;
      67             :         msg_callback_t fn;
      68             : };
      69             : 
      70             : /* an individual message */
      71             : 
      72             : static void irpc_handler(struct imessaging_context *,
      73             :                          void *,
      74             :                          uint32_t,
      75             :                          struct server_id,
      76             :                          size_t,
      77             :                          int *,
      78             :                          DATA_BLOB *);
      79             : 
      80             : 
      81             : /*
      82             :  A useful function for testing the message system.
      83             : */
      84        2725 : static void ping_message(struct imessaging_context *msg,
      85             :                          void *private_data,
      86             :                          uint32_t msg_type,
      87             :                          struct server_id src,
      88             :                          size_t num_fds,
      89             :                          int *fds,
      90             :                          DATA_BLOB *data)
      91             : {
      92           0 :         struct server_id_buf idbuf;
      93             : 
      94        2725 :         if (num_fds != 0) {
      95           0 :                 DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
      96           0 :                 return;
      97             :         }
      98             : 
      99        2725 :         DEBUG(1,("INFO: Received PING message from server %s [%.*s]\n",
     100             :                  server_id_str_buf(src, &idbuf), (int)data->length,
     101             :                  data->data?(const char *)data->data:""));
     102        2725 :         imessaging_send(msg, src, MSG_PONG, data);
     103             : }
     104             : 
     105           0 : static void pool_message(struct imessaging_context *msg,
     106             :                          void *private_data,
     107             :                          uint32_t msg_type,
     108             :                          struct server_id src,
     109             :                          size_t num_fds,
     110             :                          int *fds,
     111             :                          DATA_BLOB *data)
     112             : {
     113           0 :         FILE *f = NULL;
     114             : 
     115           0 :         if (num_fds != 1) {
     116           0 :                 DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
     117           0 :                 return;
     118             :         }
     119             : 
     120           0 :         f = fdopen(fds[0], "w");
     121           0 :         if (f == NULL) {
     122           0 :                 DBG_DEBUG("fopen failed: %s\n", strerror(errno));
     123           0 :                 return;
     124             :         }
     125             : 
     126           0 :         talloc_full_report_printf(NULL, f);
     127           0 :         fclose(f);
     128             : }
     129             : 
     130           0 : static void ringbuf_log_msg(struct imessaging_context *msg,
     131             :                             void *private_data,
     132             :                             uint32_t msg_type,
     133             :                             struct server_id src,
     134             :                             size_t num_fds,
     135             :                             int *fds,
     136             :                             DATA_BLOB *data)
     137             : {
     138           0 :         char *log = debug_get_ringbuf();
     139           0 :         size_t logsize = debug_get_ringbuf_size();
     140           0 :         DATA_BLOB blob;
     141             : 
     142           0 :         if (num_fds != 0) {
     143           0 :                 DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
     144           0 :                 return;
     145             :         }
     146             : 
     147           0 :         if (log == NULL) {
     148           0 :                 log = discard_const_p(char, "*disabled*\n");
     149           0 :                 logsize = strlen(log) + 1;
     150             :         }
     151             : 
     152           0 :         blob.data = (uint8_t *)log;
     153           0 :         blob.length = logsize;
     154             : 
     155           0 :         imessaging_send(msg, src, MSG_RINGBUF_LOG, &blob);
     156             : }
     157             : 
     158             : /****************************************************************************
     159             :  Receive a "set debug level" message.
     160             : ****************************************************************************/
     161             : 
     162           0 : static void debug_imessage(struct imessaging_context *msg_ctx,
     163             :                            void *private_data,
     164             :                            uint32_t msg_type,
     165             :                            struct server_id src,
     166             :                            size_t num_fds,
     167             :                            int *fds,
     168             :                            DATA_BLOB *data)
     169             : {
     170           0 :         const char *params_str = (const char *)data->data;
     171           0 :         struct server_id_buf src_buf;
     172           0 :         struct server_id dst = imessaging_get_server_id(msg_ctx);
     173           0 :         struct server_id_buf dst_buf;
     174             : 
     175           0 :         if (num_fds != 0) {
     176           0 :                 DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
     177           0 :                 return;
     178             :         }
     179             : 
     180             :         /* Check, it's a proper string! */
     181           0 :         if (params_str[(data->length)-1] != '\0') {
     182           0 :                 DBG_ERR("Invalid debug message from pid %s to pid %s\n",
     183             :                         server_id_str_buf(src, &src_buf),
     184             :                         server_id_str_buf(dst, &dst_buf));
     185           0 :                 return;
     186             :         }
     187             : 
     188           0 :         DBG_ERR("INFO: Remote set of debug to `%s' (pid %s from pid %s)\n",
     189             :                 params_str,
     190             :                 server_id_str_buf(dst, &dst_buf),
     191             :                 server_id_str_buf(src, &src_buf));
     192             : 
     193           0 :         debug_parse_levels(params_str);
     194             : }
     195             : 
     196             : /****************************************************************************
     197             :  Return current debug level.
     198             : ****************************************************************************/
     199             : 
     200           0 : static void debuglevel_imessage(struct imessaging_context *msg_ctx,
     201             :                                 void *private_data,
     202             :                                 uint32_t msg_type,
     203             :                                 struct server_id src,
     204             :                                 size_t num_fds,
     205             :                                 int *fds,
     206             :                                 DATA_BLOB *data)
     207             : {
     208           0 :         char *message = debug_list_class_names_and_levels();
     209           0 :         DATA_BLOB blob = data_blob_null;
     210           0 :         struct server_id_buf src_buf;
     211           0 :         struct server_id dst = imessaging_get_server_id(msg_ctx);
     212           0 :         struct server_id_buf dst_buf;
     213             : 
     214           0 :         if (num_fds != 0) {
     215           0 :                 DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
     216           0 :                 return;
     217             :         }
     218             : 
     219           0 :         DBG_DEBUG("Received REQ_DEBUGLEVEL message (pid %s from pid %s)\n",
     220             :                   server_id_str_buf(dst, &dst_buf),
     221             :                   server_id_str_buf(src, &src_buf));
     222             : 
     223           0 :         if (message == NULL) {
     224           0 :                 DBG_ERR("debug_list_class_names_and_levels returned NULL\n");
     225           0 :                 return;
     226             :         }
     227             : 
     228           0 :         blob = data_blob_string_const_null(message);
     229           0 :         imessaging_send(msg_ctx, src, MSG_DEBUGLEVEL, &blob);
     230             : 
     231           0 :         TALLOC_FREE(message);
     232             : }
     233             : 
     234             : /*
     235             :   return uptime of messaging server via irpc
     236             : */
     237           0 : static NTSTATUS irpc_uptime(struct irpc_message *msg,
     238             :                             struct irpc_uptime *r)
     239             : {
     240           0 :         struct imessaging_context *ctx = talloc_get_type(msg->private_data, struct imessaging_context);
     241           0 :         *r->out.start_time = timeval_to_nttime(&ctx->start_time);
     242           0 :         return NT_STATUS_OK;
     243             : }
     244             : 
     245       75771 : static struct dispatch_fn *imessaging_find_dispatch(
     246             :         struct imessaging_context *msg, uint32_t msg_type)
     247             : {
     248             :         /* temporary IDs use an idtree, the rest use a array of pointers */
     249       75771 :         if (msg_type >= MSG_TMP_BASE) {
     250       24572 :                 return (struct dispatch_fn *)idr_find(msg->dispatch_tree,
     251             :                                                       msg_type);
     252             :         }
     253       51199 :         if (msg_type < msg->num_types) {
     254       51199 :                 return msg->dispatch[msg_type];
     255             :         }
     256           0 :         return NULL;
     257             : }
     258             : 
     259             : /*
     260             :   Register a dispatch function for a particular message type.
     261             : */
     262     3309602 : NTSTATUS imessaging_register(struct imessaging_context *msg, void *private_data,
     263             :                             uint32_t msg_type, msg_callback_t fn)
     264             : {
     265      137903 :         struct dispatch_fn *d;
     266             : 
     267             :         /* possibly expand dispatch array */
     268     3309602 :         if (msg_type >= msg->num_types) {
     269       51714 :                 struct dispatch_fn **dp;
     270       51714 :                 uint32_t i;
     271     1239459 :                 dp = talloc_realloc(msg, msg->dispatch, struct dispatch_fn *, msg_type+1);
     272     1239459 :                 NT_STATUS_HAVE_NO_MEMORY(dp);
     273     1239459 :                 msg->dispatch = dp;
     274   743142407 :                 for (i=msg->num_types;i<=msg_type;i++) {
     275   741902948 :                         msg->dispatch[i] = NULL;
     276             :                 }
     277     1239459 :                 msg->num_types = msg_type+1;
     278             :         }
     279             : 
     280     3309602 :         d = talloc_zero(msg->dispatch, struct dispatch_fn);
     281     3309602 :         NT_STATUS_HAVE_NO_MEMORY(d);
     282     3309602 :         d->msg_type = msg_type;
     283     3309602 :         d->private_data = private_data;
     284     3309602 :         d->fn = fn;
     285             : 
     286     3309602 :         DLIST_ADD(msg->dispatch[msg_type], d);
     287             : 
     288     3309602 :         return NT_STATUS_OK;
     289             : }
     290             : 
     291             : /*
     292             :   register a temporary message handler. The msg_type is allocated
     293             :   above MSG_TMP_BASE
     294             : */
     295           8 : NTSTATUS imessaging_register_tmp(struct imessaging_context *msg, void *private_data,
     296             :                                 msg_callback_t fn, uint32_t *msg_type)
     297             : {
     298           3 :         struct dispatch_fn *d;
     299           3 :         int id;
     300             : 
     301           8 :         d = talloc_zero(msg->dispatch, struct dispatch_fn);
     302           8 :         NT_STATUS_HAVE_NO_MEMORY(d);
     303           8 :         d->private_data = private_data;
     304           8 :         d->fn = fn;
     305             : 
     306           8 :         id = idr_get_new_above(msg->dispatch_tree, d, MSG_TMP_BASE, UINT16_MAX);
     307           8 :         if (id == -1) {
     308           0 :                 talloc_free(d);
     309           0 :                 return NT_STATUS_TOO_MANY_CONTEXT_IDS;
     310             :         }
     311             : 
     312           8 :         d->msg_type = (uint32_t)id;
     313           8 :         (*msg_type) = d->msg_type;
     314             : 
     315           8 :         return NT_STATUS_OK;
     316             : }
     317             : 
     318             : /*
     319             :   De-register the function for a particular message type. Return the number of
     320             :   functions deregistered.
     321             : */
     322        4573 : size_t imessaging_deregister(struct imessaging_context *msg, uint32_t msg_type, void *private_data)
     323             : {
     324           0 :         struct dispatch_fn *d, *next;
     325        4573 :         size_t removed = 0;
     326             : 
     327        4573 :         if (msg_type >= msg->num_types) {
     328           5 :                 d = (struct dispatch_fn *)idr_find(msg->dispatch_tree,
     329             :                                                    msg_type);
     330           5 :                 if (!d) return 0;
     331           5 :                 idr_remove(msg->dispatch_tree, msg_type);
     332           5 :                 talloc_free(d);
     333           5 :                 return 1;
     334             :         }
     335             : 
     336        9198 :         for (d = msg->dispatch[msg_type]; d; d = next) {
     337        4630 :                 next = d->next;
     338        4630 :                 if (d->private_data == private_data) {
     339        4568 :                         DLIST_REMOVE(msg->dispatch[msg_type], d);
     340        4568 :                         talloc_free(d);
     341        4568 :                         ++removed;
     342             :                 }
     343             :         }
     344             : 
     345        4568 :         return removed;
     346             : }
     347             : 
     348             : /*
     349             : */
     350      129463 : int imessaging_cleanup(struct imessaging_context *msg)
     351             : {
     352      129463 :         return 0;
     353             : }
     354             : 
     355             : static void imessaging_dgm_recv(struct tevent_context *ev,
     356             :                                 const uint8_t *buf, size_t buf_len,
     357             :                                 int *fds, size_t num_fds,
     358             :                                 void *private_data);
     359             : 
     360             : /* Keep a list of imessaging contexts */
     361             : static struct imessaging_context *msg_ctxs;
     362             : 
     363             : /*
     364             :  * A process has terminated, clean-up any names it has registered.
     365             :  */
     366         809 : NTSTATUS imessaging_process_cleanup(
     367             :         struct imessaging_context *msg_ctx,
     368             :         pid_t pid)
     369             : {
     370         809 :         struct irpc_name_records *names = NULL;
     371         809 :         uint32_t i = 0;
     372         809 :         uint32_t j = 0;
     373         809 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     374             : 
     375         809 :         if (mem_ctx == NULL) {
     376           0 :                 DBG_ERR("OOM unable to clean up messaging for process (%d)\n",
     377             :                         pid);
     378           0 :                 return NT_STATUS_NO_MEMORY;
     379             :         }
     380             : 
     381         809 :         names = irpc_all_servers(msg_ctx, mem_ctx);
     382         809 :         if (names == NULL) {
     383           0 :                 TALLOC_FREE(mem_ctx);
     384           0 :                 return NT_STATUS_OK;
     385             :         }
     386       16031 :         for (i = 0; i < names->num_records; i++) {
     387       33367 :                 for (j = 0; j < names->names[i]->count; j++) {
     388       18145 :                         if (names->names[i]->ids[j].pid == pid) {
     389         951 :                                 int ret = server_id_db_prune_name(
     390             :                                         msg_ctx->names,
     391         877 :                                         names->names[i]->name,
     392         877 :                                         names->names[i]->ids[j]);
     393         951 :                                 if (ret != 0 && ret != ENOENT) {
     394           0 :                                         TALLOC_FREE(mem_ctx);
     395           0 :                                         return map_nt_error_from_unix_common(
     396             :                                             ret);
     397             :                                 }
     398             :                         }
     399             :                 }
     400             :         }
     401         809 :         TALLOC_FREE(mem_ctx);
     402         809 :         return NT_STATUS_OK;
     403             : }
     404             : 
     405      457197 : static int imessaging_context_destructor(struct imessaging_context *msg)
     406             : {
     407      457197 :         struct irpc_request *irpc = NULL;
     408      457197 :         struct irpc_request *next = NULL;
     409             : 
     410      457197 :         for (irpc = msg->requests; irpc != NULL; irpc = next) {
     411           0 :                 next = irpc->next;
     412             : 
     413           0 :                 DLIST_REMOVE(msg->requests, irpc);
     414           0 :                 irpc->callid = -1;
     415             :         }
     416             : 
     417      457197 :         DLIST_REMOVE(msg_ctxs, msg);
     418      457197 :         TALLOC_FREE(msg->msg_dgm_ref);
     419      457197 :         return 0;
     420             : }
     421             : 
     422             : /*
     423             :  * Cleanup messaging dgm contexts on a specific event context.
     424             :  *
     425             :  * We must make sure to unref all messaging_dgm_ref's *before* the
     426             :  * tevent context goes away. Only when the last ref is freed, the
     427             :  * refcounted messaging dgm context will be freed.
     428             :  */
     429         587 : void imessaging_dgm_unref_ev(struct tevent_context *ev)
     430             : {
     431         587 :         struct imessaging_context *msg = NULL;
     432             : 
     433        3003 :         for (msg = msg_ctxs; msg != NULL; msg = msg->next) {
     434        2416 :                 if (msg->ev == ev) {
     435        1724 :                         TALLOC_FREE(msg->msg_dgm_ref);
     436             :                 }
     437             :         }
     438         587 : }
     439             : 
     440       58446 : static NTSTATUS imessaging_reinit(struct imessaging_context *msg)
     441             : {
     442       58446 :         int ret = -1;
     443             : 
     444       58446 :         TALLOC_FREE(msg->msg_dgm_ref);
     445             : 
     446       58446 :         if (msg->discard_incoming) {
     447       24646 :                 msg->num_incoming_listeners = 0;
     448             :         } else {
     449       33800 :                 msg->num_incoming_listeners = 1;
     450             :         }
     451             : 
     452       58446 :         msg->server_id.pid = getpid();
     453             : 
     454       58446 :         msg->msg_dgm_ref = messaging_dgm_ref(msg,
     455             :                                 msg->ev,
     456             :                                 &msg->server_id.unique_id,
     457             :                                 msg->sock_dir,
     458             :                                 msg->lock_dir,
     459             :                                 imessaging_dgm_recv,
     460             :                                 msg,
     461             :                                 &ret);
     462             : 
     463       58446 :         if (msg->msg_dgm_ref == NULL) {
     464           0 :                 DEBUG(2, ("messaging_dgm_ref failed: %s\n",
     465             :                         strerror(ret)));
     466           0 :                 return map_nt_error_from_unix_common(ret);
     467             :         }
     468             : 
     469       58446 :         server_id_db_reinit(msg->names, msg->server_id);
     470       58446 :         return NT_STATUS_OK;
     471             : }
     472             : 
     473             : /*
     474             :  * Must be called after a fork.
     475             :  */
     476       16826 : NTSTATUS imessaging_reinit_all(void)
     477             : {
     478       16826 :         struct imessaging_context *msg = NULL;
     479             : 
     480       75272 :         for (msg = msg_ctxs; msg != NULL; msg = msg->next) {
     481       58446 :                 NTSTATUS status = imessaging_reinit(msg);
     482       58446 :                 if (!NT_STATUS_IS_OK(status)) {
     483           0 :                         return status;
     484             :                 }
     485             :         }
     486       16826 :         return NT_STATUS_OK;
     487             : }
     488             : 
     489             : /*
     490             :   create the listening socket and setup the dispatcher
     491             : */
     492      413100 : static struct imessaging_context *imessaging_init_internal(
     493             :                                            TALLOC_CTX *mem_ctx,
     494             :                                            bool discard_incoming,
     495             :                                            struct loadparm_context *lp_ctx,
     496             :                                            struct server_id server_id,
     497             :                                            struct tevent_context *ev)
     498             : {
     499       17237 :         NTSTATUS status;
     500       17237 :         struct imessaging_context *msg;
     501       17237 :         bool ok;
     502       17237 :         int ret;
     503      413100 :         const char *lock_dir = NULL;
     504      413100 :         int tdb_flags = TDB_INCOMPATIBLE_HASH | TDB_CLEAR_IF_FIRST;
     505             : 
     506      413100 :         if (ev == NULL) {
     507           0 :                 return NULL;
     508             :         }
     509             : 
     510      413100 :         msg = talloc_zero(mem_ctx, struct imessaging_context);
     511      413100 :         if (msg == NULL) {
     512           0 :                 return NULL;
     513             :         }
     514      413100 :         msg->ev = ev;
     515      413100 :         msg->discard_incoming = discard_incoming;
     516      413100 :         if (msg->discard_incoming) {
     517      282789 :                 msg->num_incoming_listeners = 0;
     518             :         } else {
     519      130311 :                 msg->num_incoming_listeners = 1;
     520             :         }
     521             : 
     522      413100 :         talloc_set_destructor(msg, imessaging_context_destructor);
     523             : 
     524             :         /* create the messaging directory if needed */
     525             : 
     526      413100 :         lock_dir = lpcfg_lock_directory(lp_ctx);
     527      413100 :         if (lock_dir == NULL) {
     528           0 :                 goto fail;
     529             :         }
     530             : 
     531      413100 :         msg->sock_dir = lpcfg_private_path(msg, lp_ctx, "msg.sock");
     532      413100 :         if (msg->sock_dir == NULL) {
     533           0 :                 goto fail;
     534             :         }
     535      413100 :         ok = directory_create_or_exist_strict(msg->sock_dir, geteuid(), 0700);
     536      413100 :         if (!ok) {
     537          14 :                 goto fail;
     538             :         }
     539             : 
     540      413086 :         msg->lock_dir = lpcfg_lock_path(msg, lp_ctx, "msg.lock");
     541      413086 :         if (msg->lock_dir == NULL) {
     542           0 :                 goto fail;
     543             :         }
     544      413086 :         ok = directory_create_or_exist_strict(msg->lock_dir, geteuid(), 0755);
     545      413086 :         if (!ok) {
     546           0 :                 goto fail;
     547             :         }
     548             : 
     549      413086 :         msg->msg_dgm_ref = messaging_dgm_ref(
     550             :                 msg, ev, &server_id.unique_id, msg->sock_dir, msg->lock_dir,
     551             :                 imessaging_dgm_recv, msg, &ret);
     552             : 
     553      413086 :         if (msg->msg_dgm_ref == NULL) {
     554           8 :                 goto fail;
     555             :         }
     556             : 
     557      413078 :         msg->server_id     = server_id;
     558      413078 :         msg->idr           = idr_init(msg);
     559      413078 :         if (msg->idr == NULL) {
     560           0 :                 goto fail;
     561             :         }
     562             : 
     563      413078 :         msg->dispatch_tree = idr_init(msg);
     564      413078 :         if (msg->dispatch_tree == NULL) {
     565           0 :                 goto fail;
     566             :         }
     567             : 
     568      413078 :         msg->start_time    = timeval_current();
     569             : 
     570      413078 :         tdb_flags |= lpcfg_tdb_flags(lp_ctx, 0);
     571             : 
     572             :         /*
     573             :          * This context holds a destructor that cleans up any names
     574             :          * registered on this context on talloc_free()
     575             :          */
     576      413078 :         msg->names = server_id_db_init(msg, server_id, lock_dir, 0, tdb_flags);
     577      413078 :         if (msg->names == NULL) {
     578           0 :                 goto fail;
     579             :         }
     580             : 
     581      413078 :         status = imessaging_register(msg, NULL, MSG_PING, ping_message);
     582      413078 :         if (!NT_STATUS_IS_OK(status)) {
     583           0 :                 goto fail;
     584             :         }
     585      413078 :         status = imessaging_register(msg, NULL, MSG_REQ_POOL_USAGE,
     586             :                                      pool_message);
     587      413078 :         if (!NT_STATUS_IS_OK(status)) {
     588           0 :                 goto fail;
     589             :         }
     590      413078 :         status = imessaging_register(msg, NULL, MSG_IRPC, irpc_handler);
     591      413078 :         if (!NT_STATUS_IS_OK(status)) {
     592           0 :                 goto fail;
     593             :         }
     594      413078 :         status = imessaging_register(msg, NULL, MSG_REQ_RINGBUF_LOG,
     595             :                                      ringbuf_log_msg);
     596      413078 :         if (!NT_STATUS_IS_OK(status)) {
     597           0 :                 goto fail;
     598             :         }
     599      413078 :         status = imessaging_register(msg, NULL, MSG_DEBUG,
     600             :                                      debug_imessage);
     601      413078 :         if (!NT_STATUS_IS_OK(status)) {
     602           0 :                 goto fail;
     603             :         }
     604      413078 :         status = imessaging_register(msg, NULL, MSG_REQ_DEBUGLEVEL,
     605             :                                      debuglevel_imessage);
     606      413078 :         if (!NT_STATUS_IS_OK(status)) {
     607           0 :                 goto fail;
     608             :         }
     609      413078 :         status = IRPC_REGISTER(msg, irpc, IRPC_UPTIME, irpc_uptime, msg);
     610      413078 :         if (!NT_STATUS_IS_OK(status)) {
     611           0 :                 goto fail;
     612             :         }
     613             : #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
     614             :         /*
     615             :          * Register handlers for messages specific to developer and
     616             :          * self test builds
     617             :          */
     618      413078 :         status = imessaging_register_extra_handlers(msg);
     619      413078 :         if (!NT_STATUS_IS_OK(status)) {
     620           0 :                 goto fail;
     621             :         }
     622             : #endif /* defined(DEVELOPER) || defined(ENABLE_SELFTEST) */
     623             : 
     624      413078 :         DLIST_ADD(msg_ctxs, msg);
     625             : 
     626      395843 :         return msg;
     627          22 : fail:
     628          22 :         talloc_free(msg);
     629          22 :         return NULL;
     630             : }
     631             : 
     632             : /*
     633             :   create the listening socket and setup the dispatcher
     634             : */
     635      130311 : struct imessaging_context *imessaging_init(TALLOC_CTX *mem_ctx,
     636             :                                            struct loadparm_context *lp_ctx,
     637             :                                            struct server_id server_id,
     638             :                                            struct tevent_context *ev)
     639             : {
     640      130311 :         bool discard_incoming = false;
     641      130311 :         return imessaging_init_internal(mem_ctx,
     642             :                                         discard_incoming,
     643             :                                         lp_ctx,
     644             :                                         server_id,
     645             :                                         ev);
     646             : }
     647             : 
     648      282789 : struct imessaging_context *imessaging_init_discard_incoming(
     649             :                                                 TALLOC_CTX *mem_ctx,
     650             :                                                 struct loadparm_context *lp_ctx,
     651             :                                                 struct server_id server_id,
     652             :                                                 struct tevent_context *ev)
     653             : {
     654      282789 :         bool discard_incoming = true;
     655      282789 :         return imessaging_init_internal(mem_ctx,
     656             :                                         discard_incoming,
     657             :                                         lp_ctx,
     658             :                                         server_id,
     659             :                                         ev);
     660             : }
     661             : 
     662             : struct imessaging_post_state {
     663             :         struct imessaging_context *msg_ctx;
     664             :         struct imessaging_post_state **busy_ref;
     665             :         size_t buf_len;
     666             :         uint8_t buf[];
     667             : };
     668             : 
     669        3140 : static int imessaging_post_state_destructor(struct imessaging_post_state *state)
     670             : {
     671        3140 :         if (state->busy_ref != NULL) {
     672           0 :                 *state->busy_ref = NULL;
     673           0 :                 state->busy_ref = NULL;
     674             :         }
     675        3140 :         return 0;
     676             : }
     677             : 
     678           8 : static void imessaging_post_handler(struct tevent_context *ev,
     679             :                                     struct tevent_immediate *ti,
     680             :                                     void *private_data)
     681             : {
     682           8 :         struct imessaging_post_state *state = talloc_get_type_abort(
     683             :                 private_data, struct imessaging_post_state);
     684             : 
     685           8 :         if (state == NULL) {
     686           0 :                 return;
     687             :         }
     688             : 
     689             :         /*
     690             :          * In usecases like using messaging_client_init() with irpc processing
     691             :          * we may free the imessaging_context during the messaging handler.
     692             :          * imessaging_post_state is a child of imessaging_context and
     693             :          * might be implicitly free'ed before the explicit TALLOC_FREE(state).
     694             :          *
     695             :          * The busy_ref pointer makes sure the destructor clears
     696             :          * the local 'state' variable.
     697             :          */
     698             : 
     699           8 :         SMB_ASSERT(state->busy_ref == NULL);
     700           8 :         state->busy_ref = &state;
     701             : 
     702           8 :         imessaging_dgm_recv(ev, state->buf, state->buf_len, NULL, 0,
     703           8 :                             state->msg_ctx);
     704             : 
     705           8 :         state->busy_ref = NULL;
     706           8 :         TALLOC_FREE(state);
     707             : }
     708             : 
     709        3140 : static int imessaging_post_self(struct imessaging_context *msg,
     710             :                                 const uint8_t *buf, size_t buf_len)
     711             : {
     712           0 :         struct tevent_immediate *ti;
     713           0 :         struct imessaging_post_state *state;
     714             : 
     715        3140 :         state = talloc_size(
     716             :                 msg, offsetof(struct imessaging_post_state, buf) + buf_len);
     717        3140 :         if (state == NULL) {
     718           0 :                 return ENOMEM;
     719             :         }
     720        3140 :         talloc_set_name_const(state, "struct imessaging_post_state");
     721             : 
     722        3140 :         talloc_set_destructor(state, imessaging_post_state_destructor);
     723             : 
     724        3140 :         ti = tevent_create_immediate(state);
     725        3140 :         if (ti == NULL) {
     726           0 :                 TALLOC_FREE(state);
     727           0 :                 return ENOMEM;
     728             :         }
     729             : 
     730        3140 :         state->msg_ctx = msg;
     731        3140 :         state->busy_ref = NULL;
     732        3140 :         state->buf_len = buf_len;
     733        3140 :         memcpy(state->buf, buf, buf_len);
     734             : 
     735        3140 :         tevent_schedule_immediate(ti, msg->ev, imessaging_post_handler,
     736           0 :                                   state);
     737             : 
     738        3140 :         return 0;
     739             : }
     740             : 
     741      323843 : static void imessaging_dgm_recv(struct tevent_context *ev,
     742             :                                 const uint8_t *buf, size_t buf_len,
     743             :                                 int *fds, size_t num_fds,
     744             :                                 void *private_data)
     745             : {
     746      323843 :         struct imessaging_context *msg = talloc_get_type_abort(
     747             :                 private_data, struct imessaging_context);
     748       90976 :         uint32_t msg_type;
     749       90976 :         struct server_id src, dst;
     750       90976 :         struct server_id_buf srcbuf, dstbuf;
     751       90976 :         DATA_BLOB data;
     752             : 
     753      323843 :         if (buf_len < MESSAGE_HDR_LENGTH) {
     754             :                 /* Invalid message, ignore */
     755      117845 :                 return;
     756             :         }
     757             : 
     758      323843 :         if (msg->num_incoming_listeners == 0) {
     759         521 :                 struct server_id_buf selfbuf;
     760             : 
     761      114705 :                 message_hdr_get(&msg_type, &src, &dst, buf);
     762             : 
     763      114705 :                 DBG_DEBUG("not listening - discarding message from "
     764             :                           "src[%s] to dst[%s] (self[%s]) type=0x%x "
     765             :                           "on %s event context\n",
     766             :                            server_id_str_buf(src, &srcbuf),
     767             :                            server_id_str_buf(dst, &dstbuf),
     768             :                            server_id_str_buf(msg->server_id, &selfbuf),
     769             :                            (unsigned)msg_type,
     770             :                            (ev != msg->ev) ? "different" : "main");
     771      114705 :                 return;
     772             :         }
     773             : 
     774      209138 :         if (ev != msg->ev) {
     775           0 :                 int ret;
     776        3140 :                 ret = imessaging_post_self(msg, buf, buf_len);
     777        3140 :                 if (ret != 0) {
     778           0 :                         DBG_WARNING("imessaging_post_self failed: %s\n",
     779             :                                     strerror(ret));
     780             :                 }
     781        3140 :                 return;
     782             :         }
     783             : 
     784      205998 :         message_hdr_get(&msg_type, &src, &dst, buf);
     785             : 
     786      205998 :         data.data = discard_const_p(uint8_t, buf + MESSAGE_HDR_LENGTH);
     787      205998 :         data.length = buf_len - MESSAGE_HDR_LENGTH;
     788             : 
     789      205998 :         if ((cluster_id_equal(&dst, &msg->server_id)) ||
     790      160277 :             ((dst.task_id == 0) && (msg->server_id.pid == 0))) {
     791       45721 :                 struct dispatch_fn *d, *next;
     792             : 
     793       75771 :                 DEBUG(10, ("%s: dst %s matches my id: %s, type=0x%x\n",
     794             :                            __func__,
     795             :                            server_id_str_buf(dst, &dstbuf),
     796             :                            server_id_str_buf(msg->server_id, &srcbuf),
     797             :                            (unsigned)msg_type));
     798             : 
     799       75771 :                 d = imessaging_find_dispatch(msg, msg_type);
     800             : 
     801      192170 :                 for (; d; d = next) {
     802       70678 :                         next = d->next;
     803       70678 :                         d->fn(msg,
     804             :                               d->private_data,
     805             :                               d->msg_type,
     806             :                               src,
     807             :                               num_fds,
     808             :                               fds,
     809             :                               &data);
     810             :                 }
     811             :         } else {
     812      130227 :                 DEBUG(10, ("%s: Ignoring type=0x%x dst %s, I am %s, \n",
     813             :                            __func__, (unsigned)msg_type,
     814             :                            server_id_str_buf(dst, &dstbuf),
     815             :                            server_id_str_buf(msg->server_id, &srcbuf)));
     816             :         }
     817             : }
     818             : 
     819             : /*
     820             :    A hack, for the short term until we get 'client only' messaging in place
     821             : */
     822      243344 : struct imessaging_context *imessaging_client_init(TALLOC_CTX *mem_ctx,
     823             :                                                   struct loadparm_context *lp_ctx,
     824             :                                                 struct tevent_context *ev)
     825             : {
     826      498485 :         struct server_id id = {
     827      243344 :                 .pid = getpid(),
     828      243344 :                 .task_id = generate_random(),
     829             :                 .vnn = NONCLUSTER_VNN,
     830             : 
     831             :                 /* This is because we are not in the s3 serverid database */
     832             :                 .unique_id = SERVERID_UNIQUE_ID_NOT_TO_VERIFY,
     833             :         };
     834             : 
     835      243344 :         return imessaging_init_discard_incoming(mem_ctx, lp_ctx, id, ev);
     836             : }
     837             : 
     838             : /*
     839             :   a list of registered irpc server functions
     840             : */
     841             : struct irpc_list {
     842             :         struct irpc_list *next, *prev;
     843             :         struct GUID uuid;
     844             :         const struct ndr_interface_table *table;
     845             :         int callnum;
     846             :         irpc_function_t fn;
     847             :         void *private_data;
     848             : };
     849             : 
     850             : 
     851             : /*
     852             :   register a irpc server function
     853             : */
     854      417029 : NTSTATUS irpc_register(struct imessaging_context *msg_ctx,
     855             :                        const struct ndr_interface_table *table,
     856             :                        int callnum, irpc_function_t fn, void *private_data)
     857             : {
     858       17279 :         struct irpc_list *irpc;
     859             : 
     860             :         /* override an existing handler, if any */
     861      423930 :         for (irpc=msg_ctx->irpc; irpc; irpc=irpc->next) {
     862        6901 :                 if (irpc->table == table && irpc->callnum == callnum) {
     863           0 :                         break;
     864             :                 }
     865             :         }
     866      417029 :         if (irpc == NULL) {
     867      417029 :                 irpc = talloc(msg_ctx, struct irpc_list);
     868      417029 :                 NT_STATUS_HAVE_NO_MEMORY(irpc);
     869      417029 :                 DLIST_ADD(msg_ctx->irpc, irpc);
     870             :         }
     871             : 
     872      417029 :         irpc->table   = table;
     873      417029 :         irpc->callnum = callnum;
     874      417029 :         irpc->fn      = fn;
     875      417029 :         irpc->private_data = private_data;
     876      417029 :         irpc->uuid = irpc->table->syntax_id.uuid;
     877             : 
     878      417029 :         return NT_STATUS_OK;
     879             : }
     880             : 
     881             : 
     882             : /*
     883             :   handle an incoming irpc reply message
     884             : */
     885       16096 : static void irpc_handler_reply(struct imessaging_context *msg_ctx, struct irpc_message *m)
     886             : {
     887       10087 :         struct irpc_request *irpc;
     888             : 
     889       16096 :         irpc = (struct irpc_request *)idr_find(msg_ctx->idr, m->header.callid);
     890       16096 :         if (irpc == NULL) return;
     891             : 
     892       13829 :         irpc->incoming.handler(irpc, m);
     893             : }
     894             : 
     895             : /*
     896             :   send a irpc reply
     897             : */
     898       15577 : NTSTATUS irpc_send_reply(struct irpc_message *m, NTSTATUS status)
     899             : {
     900       10065 :         struct ndr_push *push;
     901       10065 :         DATA_BLOB packet;
     902       10065 :         enum ndr_err_code ndr_err;
     903             : 
     904       15577 :         m->header.status = status;
     905             : 
     906             :         /* setup the reply */
     907       15577 :         push = ndr_push_init_ctx(m->ndr);
     908       15577 :         if (push == NULL) {
     909           0 :                 status = NT_STATUS_NO_MEMORY;
     910           0 :                 goto failed;
     911             :         }
     912             : 
     913       15577 :         m->header.flags |= IRPC_FLAG_REPLY;
     914       15577 :         m->header.creds.token= NULL;
     915             : 
     916             :         /* construct the packet */
     917       15577 :         ndr_err = ndr_push_irpc_header(push, NDR_SCALARS|NDR_BUFFERS, &m->header);
     918       15577 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     919           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     920           0 :                 goto failed;
     921             :         }
     922             : 
     923       15577 :         ndr_err = m->irpc->table->calls[m->irpc->callnum].ndr_push(push, NDR_OUT, m->data);
     924       15577 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     925           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     926           0 :                 goto failed;
     927             :         }
     928             : 
     929             :         /* send the reply message */
     930       15577 :         packet = ndr_push_blob(push);
     931       15577 :         status = imessaging_send(m->msg_ctx, m->from, MSG_IRPC, &packet);
     932       15577 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     933             : 
     934       15577 : failed:
     935       15577 :         talloc_free(m);
     936       15577 :         return status;
     937             : }
     938             : 
     939             : /*
     940             :   handle an incoming irpc request message
     941             : */
     942       23082 : static void irpc_handler_request(struct imessaging_context *msg_ctx,
     943             :                                  struct irpc_message *m)
     944             : {
     945       10065 :         struct irpc_list *i;
     946       10065 :         void *r;
     947       10065 :         enum ndr_err_code ndr_err;
     948             : 
     949       66036 :         for (i=msg_ctx->irpc; i; i=i->next) {
     950       60380 :                 if (GUID_equal(&i->uuid, &m->header.uuid) &&
     951       46370 :                     i->table->syntax_id.if_version == m->header.if_version &&
     952       46370 :                     i->callnum == m->header.callnum) {
     953        7361 :                         break;
     954             :                 }
     955             :         }
     956             : 
     957       23082 :         if (i == NULL) {
     958             :                 /* no registered handler for this message */
     959        5656 :                 talloc_free(m);
     960        5656 :                 return;
     961             :         }
     962             : 
     963             :         /* allocate space for the structure */
     964       17426 :         r = talloc_zero_size(m->ndr, i->table->calls[m->header.callnum].struct_size);
     965       17426 :         if (r == NULL) goto failed;
     966             : 
     967       17426 :         m->ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
     968             : 
     969             :         /* parse the request data */
     970       17426 :         ndr_err = i->table->calls[i->callnum].ndr_pull(m->ndr, NDR_IN, r);
     971       17426 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) goto failed;
     972             : 
     973             :         /* make the call */
     974       17426 :         m->private_data= i->private_data;
     975       17426 :         m->defer_reply = false;
     976       17426 :         m->no_reply    = false;
     977       17426 :         m->msg_ctx     = msg_ctx;
     978       17426 :         m->irpc        = i;
     979       17426 :         m->data        = r;
     980             : 
     981       17426 :         m->header.status = i->fn(m, r);
     982             : 
     983       17426 :         if (m->no_reply) {
     984             :                 /* the server function won't ever be replying to this request */
     985        1849 :                 talloc_free(m);
     986        1849 :                 return;
     987             :         }
     988             : 
     989       15577 :         if (m->defer_reply) {
     990             :                 /* the server function has asked to defer the reply to later */
     991        1026 :                 talloc_steal(msg_ctx, m);
     992        1026 :                 return;
     993             :         }
     994             : 
     995       14551 :         irpc_send_reply(m, m->header.status);
     996       14551 :         return;
     997             : 
     998           0 : failed:
     999           0 :         talloc_free(m);
    1000             : }
    1001             : 
    1002             : /*
    1003             :   handle an incoming irpc message
    1004             : */
    1005       39178 : static void irpc_handler(struct imessaging_context *msg_ctx,
    1006             :                          void *private_data,
    1007             :                          uint32_t msg_type,
    1008             :                          struct server_id src,
    1009             :                          size_t num_fds,
    1010             :                          int *fds,
    1011             :                          DATA_BLOB *packet)
    1012             : {
    1013       20152 :         struct irpc_message *m;
    1014       20152 :         enum ndr_err_code ndr_err;
    1015             : 
    1016       39178 :         if (num_fds != 0) {
    1017           0 :                 DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
    1018           0 :                 return;
    1019             :         }
    1020             : 
    1021       39178 :         m = talloc(msg_ctx, struct irpc_message);
    1022       39178 :         if (m == NULL) goto failed;
    1023             : 
    1024       39178 :         m->from = src;
    1025             : 
    1026       39178 :         m->ndr = ndr_pull_init_blob(packet, m);
    1027       39178 :         if (m->ndr == NULL) goto failed;
    1028             : 
    1029       39178 :         m->ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
    1030             : 
    1031       39178 :         ndr_err = ndr_pull_irpc_header(m->ndr, NDR_BUFFERS|NDR_SCALARS, &m->header);
    1032       39178 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) goto failed;
    1033             : 
    1034       39178 :         if (m->header.flags & IRPC_FLAG_REPLY) {
    1035       16096 :                 irpc_handler_reply(msg_ctx, m);
    1036             :         } else {
    1037       23082 :                 irpc_handler_request(msg_ctx, m);
    1038             :         }
    1039       19026 :         return;
    1040             : 
    1041           0 : failed:
    1042           0 :         talloc_free(m);
    1043             : }
    1044             : 
    1045             : 
    1046             : /*
    1047             :   destroy a irpc request
    1048             : */
    1049       18615 : static int irpc_destructor(struct irpc_request *irpc)
    1050             : {
    1051       18615 :         if (irpc->callid != -1) {
    1052       18615 :                 DLIST_REMOVE(irpc->msg_ctx->requests, irpc);
    1053       18615 :                 idr_remove(irpc->msg_ctx->idr, irpc->callid);
    1054       18615 :                 if (irpc->msg_ctx->discard_incoming) {
    1055        2158 :                         SMB_ASSERT(irpc->msg_ctx->num_incoming_listeners > 0);
    1056             :                 } else {
    1057       16457 :                         SMB_ASSERT(irpc->msg_ctx->num_incoming_listeners > 1);
    1058             :                 }
    1059       18615 :                 irpc->msg_ctx->num_incoming_listeners -= 1;
    1060       18615 :                 irpc->callid = -1;
    1061             :         }
    1062             : 
    1063       18615 :         return 0;
    1064             : }
    1065             : 
    1066             : /*
    1067             :   add a string name that this irpc server can be called on
    1068             : 
    1069             :   It will be removed from the DB either via irpc_remove_name or on
    1070             :   talloc_free(msg_ctx->names).
    1071             : */
    1072       32126 : NTSTATUS irpc_add_name(struct imessaging_context *msg_ctx, const char *name)
    1073             : {
    1074         198 :         int ret;
    1075             : 
    1076       32126 :         ret = server_id_db_add(msg_ctx->names, name);
    1077       32126 :         if (ret != 0) {
    1078           0 :                 return map_nt_error_from_unix_common(ret);
    1079             :         }
    1080       32126 :         return NT_STATUS_OK;
    1081             : }
    1082             : 
    1083       22326 : static int all_servers_func(const char *name, unsigned num_servers,
    1084             :                             const struct server_id *servers,
    1085             :                             void *private_data)
    1086             : {
    1087       22326 :         struct irpc_name_records *name_records = talloc_get_type(
    1088             :                 private_data, struct irpc_name_records);
    1089        1126 :         struct irpc_name_record *name_record;
    1090        1126 :         uint32_t i;
    1091             : 
    1092        1126 :         name_records->names
    1093       22326 :                 = talloc_realloc(name_records, name_records->names,
    1094             :                                  struct irpc_name_record *, name_records->num_records+1);
    1095       22326 :         if (!name_records->names) {
    1096           0 :                 return -1;
    1097             :         }
    1098             : 
    1099       23452 :         name_records->names[name_records->num_records] = name_record
    1100       22326 :                 = talloc(name_records->names,
    1101             :                          struct irpc_name_record);
    1102       22326 :         if (!name_record) {
    1103           0 :                 return -1;
    1104             :         }
    1105             : 
    1106       22326 :         name_records->num_records++;
    1107             : 
    1108       22326 :         name_record->name = talloc_strdup(name_record, name);
    1109       22326 :         if (!name_record->name) {
    1110           0 :                 return -1;
    1111             :         }
    1112             : 
    1113       22326 :         name_record->count = num_servers;
    1114       22326 :         name_record->ids = talloc_array(name_record, struct server_id,
    1115             :                                         num_servers);
    1116       22326 :         if (name_record->ids == NULL) {
    1117           0 :                 return -1;
    1118             :         }
    1119       48837 :         for (i=0;i<name_record->count;i++) {
    1120       26511 :                 name_record->ids[i] = servers[i];
    1121             :         }
    1122       21200 :         return 0;
    1123             : }
    1124             : 
    1125             : /*
    1126             :   return a list of server ids for a server name
    1127             : */
    1128        1031 : struct irpc_name_records *irpc_all_servers(struct imessaging_context *msg_ctx,
    1129             :                                            TALLOC_CTX *mem_ctx)
    1130             : {
    1131          60 :         int ret;
    1132        1031 :         struct irpc_name_records *name_records = talloc_zero(mem_ctx, struct irpc_name_records);
    1133        1031 :         if (name_records == NULL) {
    1134           0 :                 return NULL;
    1135             :         }
    1136             : 
    1137        1031 :         ret = server_id_db_traverse_read(msg_ctx->names, all_servers_func,
    1138             :                                          name_records);
    1139        1031 :         if (ret == -1) {
    1140           0 :                 TALLOC_FREE(name_records);
    1141           0 :                 return NULL;
    1142             :         }
    1143             : 
    1144         971 :         return name_records;
    1145             : }
    1146             : 
    1147             : /*
    1148             :   remove a name from a messaging context
    1149             : */
    1150          58 : void irpc_remove_name(struct imessaging_context *msg_ctx, const char *name)
    1151             : {
    1152          58 :         server_id_db_remove(msg_ctx->names, name);
    1153          58 : }
    1154             : 
    1155           2 : struct server_id imessaging_get_server_id(struct imessaging_context *msg_ctx)
    1156             : {
    1157           2 :         return msg_ctx->server_id;
    1158             : }
    1159             : 
    1160             : struct irpc_bh_state {
    1161             :         struct imessaging_context *msg_ctx;
    1162             :         struct server_id server_id;
    1163             :         const struct ndr_interface_table *table;
    1164             :         uint32_t timeout;
    1165             :         struct security_token *token;
    1166             : };
    1167             : 
    1168       18615 : static bool irpc_bh_is_connected(struct dcerpc_binding_handle *h)
    1169             : {
    1170       18615 :         struct irpc_bh_state *hs = dcerpc_binding_handle_data(h,
    1171             :                                    struct irpc_bh_state);
    1172             : 
    1173       18615 :         if (!hs->msg_ctx) {
    1174           0 :                 return false;
    1175             :         }
    1176             : 
    1177        8528 :         return true;
    1178             : }
    1179             : 
    1180        3722 : static uint32_t irpc_bh_set_timeout(struct dcerpc_binding_handle *h,
    1181             :                                     uint32_t timeout)
    1182             : {
    1183        3722 :         struct irpc_bh_state *hs = dcerpc_binding_handle_data(h,
    1184             :                                    struct irpc_bh_state);
    1185        3722 :         uint32_t old = hs->timeout;
    1186             : 
    1187        3722 :         hs->timeout = timeout;
    1188             : 
    1189        3722 :         return old;
    1190             : }
    1191             : 
    1192             : struct irpc_bh_raw_call_state {
    1193             :         struct irpc_request *irpc;
    1194             :         uint32_t opnum;
    1195             :         DATA_BLOB in_data;
    1196             :         DATA_BLOB in_packet;
    1197             :         DATA_BLOB out_data;
    1198             : };
    1199             : 
    1200             : static void irpc_bh_raw_call_incoming_handler(struct irpc_request *irpc,
    1201             :                                               struct irpc_message *m);
    1202             : 
    1203       18615 : static struct tevent_req *irpc_bh_raw_call_send(TALLOC_CTX *mem_ctx,
    1204             :                                                 struct tevent_context *ev,
    1205             :                                                 struct dcerpc_binding_handle *h,
    1206             :                                                 const struct GUID *object,
    1207             :                                                 uint32_t opnum,
    1208             :                                                 uint32_t in_flags,
    1209             :                                                 const uint8_t *in_data,
    1210             :                                                 size_t in_length)
    1211             : {
    1212       10087 :         struct irpc_bh_state *hs =
    1213       18615 :                 dcerpc_binding_handle_data(h,
    1214             :                 struct irpc_bh_state);
    1215       10087 :         struct tevent_req *req;
    1216       10087 :         struct irpc_bh_raw_call_state *state;
    1217       10087 :         bool ok;
    1218       10087 :         struct irpc_header header;
    1219       10087 :         struct ndr_push *ndr;
    1220       10087 :         NTSTATUS status;
    1221       10087 :         enum ndr_err_code ndr_err;
    1222             : 
    1223       18615 :         req = tevent_req_create(mem_ctx, &state,
    1224             :                                 struct irpc_bh_raw_call_state);
    1225       18615 :         if (req == NULL) {
    1226           0 :                 return NULL;
    1227             :         }
    1228       18615 :         state->opnum = opnum;
    1229       18615 :         state->in_data.data = discard_const_p(uint8_t, in_data);
    1230       18615 :         state->in_data.length = in_length;
    1231             : 
    1232       18615 :         ok = irpc_bh_is_connected(h);
    1233       18615 :         if (!ok) {
    1234           0 :                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
    1235           0 :                 return tevent_req_post(req, ev);
    1236             :         }
    1237             : 
    1238       18615 :         state->irpc = talloc_zero(state, struct irpc_request);
    1239       18615 :         if (tevent_req_nomem(state->irpc, req)) {
    1240           0 :                 return tevent_req_post(req, ev);
    1241             :         }
    1242             : 
    1243       18615 :         state->irpc->msg_ctx  = hs->msg_ctx;
    1244       27143 :         state->irpc->callid   = idr_get_new(hs->msg_ctx->idr,
    1245        8528 :                                             state->irpc, UINT16_MAX);
    1246       18615 :         if (state->irpc->callid == -1) {
    1247           0 :                 tevent_req_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
    1248           0 :                 return tevent_req_post(req, ev);
    1249             :         }
    1250       18615 :         state->irpc->incoming.handler = irpc_bh_raw_call_incoming_handler;
    1251       18615 :         state->irpc->incoming.private_data = req;
    1252             : 
    1253             :         /* make sure we accept incoming messages */
    1254       18615 :         SMB_ASSERT(state->irpc->msg_ctx->num_incoming_listeners < UINT64_MAX);
    1255       18615 :         state->irpc->msg_ctx->num_incoming_listeners += 1;
    1256       18615 :         DLIST_ADD_END(state->irpc->msg_ctx->requests, state->irpc);
    1257       18615 :         talloc_set_destructor(state->irpc, irpc_destructor);
    1258             : 
    1259             :         /* setup the header */
    1260       18615 :         header.uuid = hs->table->syntax_id.uuid;
    1261             : 
    1262       18615 :         header.if_version = hs->table->syntax_id.if_version;
    1263       18615 :         header.callid     = state->irpc->callid;
    1264       18615 :         header.callnum    = state->opnum;
    1265       18615 :         header.flags      = 0;
    1266       18615 :         header.status     = NT_STATUS_OK;
    1267       18615 :         header.creds.token= hs->token;
    1268             : 
    1269             :         /* construct the irpc packet */
    1270       18615 :         ndr = ndr_push_init_ctx(state->irpc);
    1271       18615 :         if (tevent_req_nomem(ndr, req)) {
    1272           0 :                 return tevent_req_post(req, ev);
    1273             :         }
    1274             : 
    1275       18615 :         ndr_err = ndr_push_irpc_header(ndr, NDR_SCALARS|NDR_BUFFERS, &header);
    1276       18615 :         status = ndr_map_error2ntstatus(ndr_err);
    1277       18615 :         if (!NT_STATUS_IS_OK(status)) {
    1278           0 :                 tevent_req_nterror(req, status);
    1279           0 :                 return tevent_req_post(req, ev);
    1280             :         }
    1281             : 
    1282       18615 :         ndr_err = ndr_push_bytes(ndr, in_data, in_length);
    1283       18615 :         status = ndr_map_error2ntstatus(ndr_err);
    1284       18615 :         if (!NT_STATUS_IS_OK(status)) {
    1285           0 :                 tevent_req_nterror(req, status);
    1286           0 :                 return tevent_req_post(req, ev);
    1287             :         }
    1288             : 
    1289             :         /* and send it */
    1290       18615 :         state->in_packet = ndr_push_blob(ndr);
    1291       28702 :         status = imessaging_send(hs->msg_ctx, hs->server_id,
    1292       18615 :                                 MSG_IRPC, &state->in_packet);
    1293       18615 :         if (!NT_STATUS_IS_OK(status)) {
    1294           0 :                 tevent_req_nterror(req, status);
    1295           0 :                 return tevent_req_post(req, ev);
    1296             :         }
    1297             : 
    1298       18615 :         if (hs->timeout != IRPC_CALL_TIMEOUT_INF) {
    1299             :                 /* set timeout-callback in case caller wants that */
    1300       17649 :                 ok = tevent_req_set_endtime(req, ev, timeval_current_ofs(hs->timeout, 0));
    1301       17649 :                 if (!ok) {
    1302           0 :                         return tevent_req_post(req, ev);
    1303             :                 }
    1304             :         }
    1305             : 
    1306        8528 :         return req;
    1307             : }
    1308             : 
    1309       13829 : static void irpc_bh_raw_call_incoming_handler(struct irpc_request *irpc,
    1310             :                                               struct irpc_message *m)
    1311             : {
    1312       10087 :         struct tevent_req *req =
    1313       13829 :                 talloc_get_type_abort(irpc->incoming.private_data,
    1314             :                 struct tevent_req);
    1315       10087 :         struct irpc_bh_raw_call_state *state =
    1316       13829 :                 tevent_req_data(req,
    1317             :                 struct irpc_bh_raw_call_state);
    1318             : 
    1319       13829 :         talloc_steal(state, m);
    1320             : 
    1321       13829 :         if (!NT_STATUS_IS_OK(m->header.status)) {
    1322         224 :                 tevent_req_nterror(req, m->header.status);
    1323         224 :                 return;
    1324             :         }
    1325             : 
    1326       13605 :         state->out_data = data_blob_talloc(state,
    1327             :                 m->ndr->data + m->ndr->offset,
    1328             :                 m->ndr->data_size - m->ndr->offset);
    1329       13605 :         if ((m->ndr->data_size - m->ndr->offset) > 0 && !state->out_data.data) {
    1330           0 :                 tevent_req_oom(req);
    1331           0 :                 return;
    1332             :         }
    1333             : 
    1334       13605 :         tevent_req_done(req);
    1335             : }
    1336             : 
    1337       13829 : static NTSTATUS irpc_bh_raw_call_recv(struct tevent_req *req,
    1338             :                                         TALLOC_CTX *mem_ctx,
    1339             :                                         uint8_t **out_data,
    1340             :                                         size_t *out_length,
    1341             :                                         uint32_t *out_flags)
    1342             : {
    1343       10087 :         struct irpc_bh_raw_call_state *state =
    1344       13829 :                 tevent_req_data(req,
    1345             :                 struct irpc_bh_raw_call_state);
    1346       10087 :         NTSTATUS status;
    1347             : 
    1348       13829 :         if (tevent_req_is_nterror(req, &status)) {
    1349         224 :                 tevent_req_received(req);
    1350         224 :                 return status;
    1351             :         }
    1352             : 
    1353       13605 :         *out_data = talloc_move(mem_ctx, &state->out_data.data);
    1354       13605 :         *out_length = state->out_data.length;
    1355       13605 :         *out_flags = 0;
    1356       13605 :         tevent_req_received(req);
    1357       13605 :         return NT_STATUS_OK;
    1358             : }
    1359             : 
    1360             : struct irpc_bh_disconnect_state {
    1361             :         uint8_t _dummy;
    1362             : };
    1363             : 
    1364           0 : static struct tevent_req *irpc_bh_disconnect_send(TALLOC_CTX *mem_ctx,
    1365             :                                                 struct tevent_context *ev,
    1366             :                                                 struct dcerpc_binding_handle *h)
    1367             : {
    1368           0 :         struct irpc_bh_state *hs = dcerpc_binding_handle_data(h,
    1369             :                                      struct irpc_bh_state);
    1370           0 :         struct tevent_req *req;
    1371           0 :         struct irpc_bh_disconnect_state *state;
    1372           0 :         bool ok;
    1373             : 
    1374           0 :         req = tevent_req_create(mem_ctx, &state,
    1375             :                                 struct irpc_bh_disconnect_state);
    1376           0 :         if (req == NULL) {
    1377           0 :                 return NULL;
    1378             :         }
    1379             : 
    1380           0 :         ok = irpc_bh_is_connected(h);
    1381           0 :         if (!ok) {
    1382           0 :                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
    1383           0 :                 return tevent_req_post(req, ev);
    1384             :         }
    1385             : 
    1386           0 :         hs->msg_ctx = NULL;
    1387             : 
    1388           0 :         tevent_req_done(req);
    1389           0 :         return tevent_req_post(req, ev);
    1390             : }
    1391             : 
    1392           0 : static NTSTATUS irpc_bh_disconnect_recv(struct tevent_req *req)
    1393             : {
    1394           0 :         NTSTATUS status;
    1395             : 
    1396           0 :         if (tevent_req_is_nterror(req, &status)) {
    1397           0 :                 tevent_req_received(req);
    1398           0 :                 return status;
    1399             :         }
    1400             : 
    1401           0 :         tevent_req_received(req);
    1402           0 :         return NT_STATUS_OK;
    1403             : }
    1404             : 
    1405       18615 : static bool irpc_bh_ref_alloc(struct dcerpc_binding_handle *h)
    1406             : {
    1407       18615 :         return true;
    1408             : }
    1409             : 
    1410       32220 : static void irpc_bh_do_ndr_print(struct dcerpc_binding_handle *h,
    1411             :                                  ndr_flags_type ndr_flags,
    1412             :                                  const void *_struct_ptr,
    1413             :                                  const struct ndr_interface_call *call)
    1414             : {
    1415       32220 :         void *struct_ptr = discard_const(_struct_ptr);
    1416       32220 :         bool print_in = false;
    1417       32220 :         bool print_out = false;
    1418             : 
    1419       32220 :         if (DEBUGLEVEL >= 11) {
    1420           0 :                 print_in = true;
    1421           0 :                 print_out = true;
    1422             :         }
    1423             : 
    1424       32220 :         if (ndr_flags & NDR_IN) {
    1425       18615 :                 if (print_in) {
    1426           0 :                         ndr_print_function_debug(call->ndr_print,
    1427           0 :                                                  call->name,
    1428             :                                                  ndr_flags,
    1429             :                                                  struct_ptr);
    1430             :                 }
    1431             :         }
    1432       32220 :         if (ndr_flags & NDR_OUT) {
    1433       13605 :                 if (print_out) {
    1434           0 :                         ndr_print_function_debug(call->ndr_print,
    1435           0 :                                                  call->name,
    1436             :                                                  ndr_flags,
    1437             :                                                  struct_ptr);
    1438             :                 }
    1439             :         }
    1440       32220 : }
    1441             : 
    1442             : static const struct dcerpc_binding_handle_ops irpc_bh_ops = {
    1443             :         .name                   = "wbint",
    1444             :         .is_connected           = irpc_bh_is_connected,
    1445             :         .set_timeout            = irpc_bh_set_timeout,
    1446             :         .raw_call_send          = irpc_bh_raw_call_send,
    1447             :         .raw_call_recv          = irpc_bh_raw_call_recv,
    1448             :         .disconnect_send        = irpc_bh_disconnect_send,
    1449             :         .disconnect_recv        = irpc_bh_disconnect_recv,
    1450             : 
    1451             :         .ref_alloc              = irpc_bh_ref_alloc,
    1452             :         .do_ndr_print           = irpc_bh_do_ndr_print,
    1453             : };
    1454             : 
    1455             : /* initialise a irpc binding handle */
    1456        8551 : struct dcerpc_binding_handle *irpc_binding_handle(TALLOC_CTX *mem_ctx,
    1457             :                                                   struct imessaging_context *msg_ctx,
    1458             :                                                   struct server_id server_id,
    1459             :                                                   const struct ndr_interface_table *table)
    1460             : {
    1461          29 :         struct dcerpc_binding_handle *h;
    1462          29 :         struct irpc_bh_state *hs;
    1463             : 
    1464        8551 :         h = dcerpc_binding_handle_create(mem_ctx,
    1465             :                                          &irpc_bh_ops,
    1466             :                                          NULL,
    1467             :                                          table,
    1468             :                                          &hs,
    1469             :                                          struct irpc_bh_state,
    1470             :                                          __location__);
    1471        8551 :         if (h == NULL) {
    1472           0 :                 return NULL;
    1473             :         }
    1474        8551 :         hs->msg_ctx = msg_ctx;
    1475        8551 :         hs->server_id = server_id;
    1476        8551 :         hs->table = table;
    1477        8551 :         hs->timeout = IRPC_CALL_TIMEOUT;
    1478             : 
    1479        8551 :         return h;
    1480             : }
    1481             : 
    1482        8794 : struct dcerpc_binding_handle *irpc_binding_handle_by_name(TALLOC_CTX *mem_ctx,
    1483             :                                                           struct imessaging_context *msg_ctx,
    1484             :                                                           const char *dest_task,
    1485             :                                                           const struct ndr_interface_table *table)
    1486             : {
    1487          47 :         struct dcerpc_binding_handle *h;
    1488          47 :         unsigned num_sids;
    1489          47 :         struct server_id *sids;
    1490          47 :         struct server_id sid;
    1491          47 :         NTSTATUS status;
    1492             : 
    1493             :         /* find the server task */
    1494             : 
    1495        8794 :         status = irpc_servers_byname(msg_ctx, mem_ctx, dest_task,
    1496             :                                      &num_sids, &sids);
    1497        8794 :         if (!NT_STATUS_IS_OK(status)) {
    1498         250 :                 errno = EADDRNOTAVAIL;
    1499         250 :                 return NULL;
    1500             :         }
    1501        8544 :         sid = sids[0];
    1502        8544 :         talloc_free(sids);
    1503             : 
    1504        8544 :         h = irpc_binding_handle(mem_ctx, msg_ctx,
    1505             :                                 sid, table);
    1506        8544 :         if (h == NULL) {
    1507           0 :                 return NULL;
    1508             :         }
    1509             : 
    1510        8522 :         return h;
    1511             : }
    1512             : 
    1513        2227 : void irpc_binding_handle_add_security_token(struct dcerpc_binding_handle *h,
    1514             :                                             struct security_token *token)
    1515             : {
    1516           0 :         struct irpc_bh_state *hs =
    1517        2227 :                 dcerpc_binding_handle_data(h,
    1518             :                 struct irpc_bh_state);
    1519             : 
    1520        2227 :         hs->token = token;
    1521        2227 : }

Generated by: LCOV version 1.14