]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3/rpc_server: Add worker status smbcontrol message support
authorNoel Power <noel.power@suse.com>
Wed, 11 Feb 2026 08:45:33 +0000 (08:45 +0000)
committerNoel Power <npower@samba.org>
Tue, 14 Apr 2026 12:12:07 +0000 (12:12 +0000)
Add information about the number of connections a rpc_worker
process is handling and when each connection was initiated.

command
  smbcontrol 55063 rpc-dump-worker-status

will output data like below:

  rpcd_spoolss pid 55063:
      num connections = 2
      num_association_groups = 2
      last client connection 2026/03/18 06:51:04.482192
      last client disconnection 2026/03/18 06:51:00.304951
   active connections:
      [1] endpoint=ncacn_np:[\pipe\spoolss] client addr=192.168.32.175 server=priu0002 connected at 2026/03/18 06:51:04.482192
      [2] endpoint=ncacn_np:[\pipe\spoolss] client addr=192.168.33.232 server=priu0002 connected at 2026/03/18 06:47:08.466157

Signed-off-by: Noel Power <noel.power@suse.com>
Reviewed-by: Volker Lendecke <vl@samba.org>
Autobuild-User(master): Noel Power <npower@samba.org>
Autobuild-Date(master): Tue Apr 14 12:12:07 UTC 2026 on atb-devel-224

librpc/idl/messaging.idl
source3/rpc_server/rpc_server.h
source3/rpc_server/rpc_worker.c
source3/utils/smbcontrol.c

index 9bf15fc670832ac50a71dd355a68b26a01a31528..035e568b38f357649866eb24351ece560f1e6964 100644 (file)
@@ -171,6 +171,7 @@ interface messaging
                MSG_RPC_HOST_NEW_CLIENT         = 4004,
                MSG_RPC_WORKER_STATUS           = 4005,
                MSG_RPC_DUMP_STATUS             = 4006,
+               MSG_RPC_WORKER_INFO             = 4007,
 
                /*
                 * source4 allows new messages to be registered at
index 73cd78ac6a419891eb2cf1cd35e1cc9aceccb43a..e2ade2c71c3b5558625b1c09343c1a1e0422104a 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "librpc/rpc/dcesrv_core.h"
 #include "rpc_pipes.h"
+#include "lib/util/time_basic.h"
 
 struct auth_session_info;
 struct cli_credentials;
@@ -42,7 +43,9 @@ struct dcerpc_ncacn_conn {
        struct dcesrv_endpoint *endpoint;
 
        char *remote_client_name;
+       char *remote_client_addr;
        char *local_server_name;
+       struct timeval tv;
 };
 
 void set_incoming_fault(struct pipes_struct *p);
index e9dc56ef9834403b1409533998421b7cbb60cddb..b6d3420f61d15165cbcaa11ee1b96fca25e68754 100644 (file)
@@ -76,6 +76,8 @@ struct rpc_worker {
        struct rpc_worker_status status;
 
        bool done;
+       struct timeval last_connect;
+       struct timeval last_disconnect;
 };
 
 static void rpc_worker_print_interface(
@@ -159,6 +161,7 @@ static void rpc_worker_connection_terminated(
 
        worker->status.num_connections -= 1;
 
+       GetTimeOfDay(&worker->last_disconnect);
        status = rpc_worker_report_status(worker);
        if (!NT_STATUS_IS_OK(status)) {
                DBG_DEBUG("rpc_worker_report_status returned %s\n",
@@ -361,6 +364,14 @@ static void rpc_worker_new_client(
                                  info8->local_server_name);
                        goto fail;
                }
+
+               ncacn_conn->remote_client_addr = talloc_strdup(
+                       ncacn_conn, info8->remote_client_addr);
+               if (ncacn_conn->remote_client_addr == NULL) {
+                       DBG_DEBUG("talloc_strdup(%s) failed\n",
+                                 info8->remote_client_addr);
+                       goto fail;
+               }
        }
 
        if (transport == NCACN_NP) {
@@ -484,9 +495,10 @@ static void rpc_worker_new_client(
 
        TALLOC_FREE(client);
 
+       GetTimeOfDay(&ncacn_conn->tv);
        DLIST_ADD(worker->conns, ncacn_conn);
        worker->status.num_connections += 1;
-
+       worker->last_connect = ncacn_conn->tv;
        dcesrv_loop_next_packet(dcesrv_conn, pkt, buffer);
 
        return;
@@ -561,6 +573,82 @@ static bool rpc_worker_new_client_filter(
        return false;
 }
 
+static void dump_worker_client_info(TALLOC_CTX *root,
+                                   struct rpc_worker *worker,
+                                   FILE *f)
+{
+       struct dcerpc_ncacn_conn *conn = NULL;
+       struct timeval_buf buf_con = {0};
+       struct timeval_buf buf_discon = {0};
+       int i = 1;
+       fprintf(f,
+               "%s pid %u:\n"
+               "      num_connections = %" PRIu32 "\n"
+               "      num_association_groups = %" PRIu32 "\n"
+               "      last client connection %s\n"
+               "      last client disconnection %s\n",
+               getprogname(),
+               (unsigned int)getpid(),
+               worker->status.num_connections,
+               worker->status.num_association_groups,
+               (worker->last_connect.tv_sec != 0)
+                       ? timeval_str_buf(
+                                 &worker->last_connect, false, true, &buf_con)
+                       : "N/A",
+               (worker->last_disconnect.tv_sec != 0)
+                       ? timeval_str_buf(&worker->last_disconnect,
+                                         false,
+                                         true,
+                                         &buf_discon)
+                       : "N/A");
+       for (conn = worker->conns; conn != NULL; conn = conn->next) {
+               char *endpoint = NULL;
+               struct timeval_buf tvbuf = {0};
+               endpoint = dcerpc_binding_string(
+                       conn, conn->endpoint->ep_description);
+               timeval_str_buf(&conn->tv, false, true, &tvbuf);
+               if (i == 1) {
+                       fprintf(f, "   active connections:\n");
+               }
+               fprintf(f,
+                       "      [%d] endpoint=%s client addr=%s server=%s "
+                       "connected at %s\n",
+                       i++,
+                       endpoint ? endpoint : "UNKNOWN",
+                       conn->remote_client_addr,
+                       conn->local_server_name,
+                       tvbuf.buf);
+               TALLOC_FREE(endpoint);
+       }
+}
+
+static bool rpc_worker_client_info(struct messaging_rec *rec,
+                                  void *private_data)
+{
+       struct rpc_worker *worker = talloc_get_type_abort(private_data,
+                                                         struct rpc_worker);
+       FILE *f = NULL;
+
+       if (rec->msg_type != MSG_RPC_WORKER_INFO) {
+               return false;
+       }
+
+       DBG_DEBUG("Got MSG_RPC_WORKER_INFO\n");
+       if (rec->num_fds != 1) {
+               DBG_DEBUG("Got %" PRIu8 " fds, expected one\n", rec->num_fds);
+               return false;
+       }
+
+       f = fdopen_keepfd(rec->fds[0], "w");
+       if (f == NULL) {
+               DBG_DEBUG("fdopen failed: %s\n", strerror(errno));
+               return false;
+       }
+       dump_worker_client_info(NULL, worker, f);
+       fclose(f);
+       return false;
+}
+
 /*
  * Return your status message processing.
  */
@@ -845,6 +933,16 @@ static struct tevent_req *rpc_worker_send(
                return tevent_req_post(req, ev);
        }
 
+       state->new_client_req = messaging_filtered_read_send(
+               w,
+               messaging_tevent_context(w->msg_ctx),
+               w->msg_ctx,
+               rpc_worker_client_info,
+               w);
+       if (tevent_req_nomem(state->new_client_req, req)) {
+               return tevent_req_post(req, ev);
+       }
+
        /* Wait for report your status messages. */
        state->status_req = messaging_filtered_read_send(
                w,
index b318f5547d5dd97a0e0f6a9e3aed4cc4a23e0b77..4660dead695b57f79bc348577abf8b33719afa29 100644 (file)
@@ -905,6 +905,32 @@ static bool do_poolusage(struct tevent_context *ev_ctx,
        return true;
 }
 
+static bool do_worker_dump(struct tevent_context *ev_ctx,
+                          struct messaging_context *msg_ctx,
+                          const struct server_id dst,
+                          const int argc,
+                          const char **argv)
+{
+       pid_t pid = procid_to_pid(&dst);
+       int stdout_fd = 1;
+
+       if (argc != 1) {
+               fprintf(stderr,
+                       "Usage: smbcontrol <dest> "
+                       "rpc-dump-worker-status\n");
+               return False;
+       }
+
+       if (pid == 0) {
+               fprintf(stderr, "Can only send to a specific PID\n");
+               return false;
+       }
+
+       messaging_send_iov(
+               msg_ctx, dst, MSG_RPC_WORKER_INFO, NULL, 0, &stdout_fd, 1);
+       return true;
+}
+
 static bool do_rpc_dump_status(
        struct tevent_context *ev_ctx,
        struct messaging_context *msg_ctx,
@@ -1621,7 +1647,14 @@ static const struct {
                .fn   = do_sleep,
                .help = "Cause the target process to sleep",
        },
-       { .name = NULL, },
+       {
+               .name = "rpc-dump-worker-status",
+               .fn = do_worker_dump,
+               .help = "Displays info about rpcd worker processes",
+       },
+       {
+               .name = NULL,
+       },
 };
 
 /* Display usage information */