From: Noel Power Date: Wed, 11 Feb 2026 08:45:33 +0000 (+0000) Subject: s3/rpc_server: Add worker status smbcontrol message support X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f0455c7430ffca4f7a94bbd8f9e5a04fa98905ee;p=thirdparty%2Fsamba.git s3/rpc_server: Add worker status smbcontrol message support 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 Reviewed-by: Volker Lendecke Autobuild-User(master): Noel Power Autobuild-Date(master): Tue Apr 14 12:12:07 UTC 2026 on atb-devel-224 --- diff --git a/librpc/idl/messaging.idl b/librpc/idl/messaging.idl index 9bf15fc6708..035e568b38f 100644 --- a/librpc/idl/messaging.idl +++ b/librpc/idl/messaging.idl @@ -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 diff --git a/source3/rpc_server/rpc_server.h b/source3/rpc_server/rpc_server.h index 73cd78ac6a4..e2ade2c71c3 100644 --- a/source3/rpc_server/rpc_server.h +++ b/source3/rpc_server/rpc_server.h @@ -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); diff --git a/source3/rpc_server/rpc_worker.c b/source3/rpc_server/rpc_worker.c index e9dc56ef983..b6d3420f61d 100644 --- a/source3/rpc_server/rpc_worker.c +++ b/source3/rpc_server/rpc_worker.c @@ -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, diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c index b318f5547d5..4660dead695 100644 --- a/source3/utils/smbcontrol.c +++ b/source3/utils/smbcontrol.c @@ -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 " + "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 */