From 55d4d36993293fee914a009f1d8f05810e347f2b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Jan 2005 00:54:57 +0000 Subject: r5102: This is a major simplification of the logic for controlling top level servers in smbd. The old code still contained a fairly bit of legacy from the time when smbd was only handling SMB connection. The new code gets rid of all of the smb_server specific code in smbd/, and creates a much simpler infrastructures for new server code. Major changes include: - simplified the process model code a lot. - got rid of the top level server and service structures completely. The top level context is now the event_context. This got rid of service.h and server.h completely (they were the most confusing parts of the old code) - added service_stream.[ch] for the helper functions that are specific to stream type services (services that handle streams, and use a logically separate process per connection) - got rid of the builtin idle_handler code in the service logic, as none of the servers were using it, and it can easily be handled by a server in future by adding its own timed_event to the event context. - fixed some major memory leaks in the rpc server code. - added registration of servers, rather than hard coding our list of possible servers. This allows for servers as modules in the future. - temporarily disabled the winbind code until I add the helper functions for that type of server - added error checking on service startup. If a configured server fails to startup then smbd doesn't startup. - cleaned up the command line handling in smbd, removing unused options (This used to be commit cf6a46c3cbde7b1eb1b86bd3882b953a2de3a42e) --- source4/rpc_server/dcerpc_server.c | 81 ++------ source4/rpc_server/dcerpc_server.h | 2 +- source4/rpc_server/dcerpc_sock.c | 307 ++++++++++++++--------------- source4/rpc_server/epmapper/rpc_epmapper.c | 5 +- 4 files changed, 173 insertions(+), 222 deletions(-) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index 575c073e46..c21ab3d883 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -28,6 +28,7 @@ #include "dlinklist.h" #include "rpc_server/dcerpc_server.h" #include "events.h" +#include "smbd/service_stream.h" /* see if two endpoints match @@ -299,7 +300,7 @@ static int dcesrv_endpoint_destructor(void *ptr) NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx, TALLOC_CTX *mem_ctx, const struct dcesrv_endpoint *ep, - struct server_connection *srv_conn, + struct stream_connection *srv_conn, struct dcesrv_connection **_p) { struct dcesrv_connection *p; @@ -333,7 +334,7 @@ NTSTATUS dcesrv_endpoint_search_connect(struct dcesrv_context *dce_ctx, TALLOC_CTX *mem_ctx, const struct dcerpc_binding *ep_description, struct auth_session_info *session_info, - struct server_connection *srv_conn, + struct stream_connection *srv_conn, struct dcesrv_connection **dce_conn_p) { NTSTATUS status; @@ -1204,7 +1205,7 @@ static NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, const char **endpoint_s } /* - initialise the dcerpc server context + initialise the dcerpc server context for ncacn_np based services */ NTSTATUS dcesrv_init_ipc_context(TALLOC_CTX *mem_ctx, struct dcesrv_context **_dce_ctx) { @@ -1218,45 +1219,6 @@ NTSTATUS dcesrv_init_ipc_context(TALLOC_CTX *mem_ctx, struct dcesrv_context **_d return NT_STATUS_OK; } -static void dcesrv_init(struct server_service *service) -{ - NTSTATUS status; - struct dcesrv_context *dce_ctx; - - DEBUG(1,("dcesrv_init\n")); - - status = dcesrv_init_context(service, - lp_dcerpc_endpoint_servers(), - DCESRV_CALL_STATE_FLAG_MAY_ASYNC, - &dce_ctx); - if (!NT_STATUS_IS_OK(status)) { - return; - } - - service->service.private_data = dce_ctx; - - dcesrv_sock_init(service); - - return; -} - -static void dcesrv_accept(struct server_connection *srv_conn) -{ - dcesrv_sock_accept(srv_conn); -} - -static void dcesrv_recv(struct server_connection *srv_conn, - struct timeval t, uint16_t flags) -{ - dcesrv_sock_recv(srv_conn, t, flags); -} - -static void dcesrv_send(struct server_connection *srv_conn, - struct timeval t, uint16_t flags) -{ - dcesrv_sock_send(srv_conn, t, flags); -} - /* the list of currently registered DCERPC endpoint servers. */ static struct ep_server { @@ -1338,32 +1300,25 @@ const struct dcesrv_critical_sizes *dcerpc_module_version(void) return &critical_sizes; } -static const struct server_stream_ops dcesrv_stream_ops = { - .name = "rpc", - .socket_init = NULL, - .accept_connection = dcesrv_accept, - .recv_handler = dcesrv_recv, - .send_handler = dcesrv_send, - .idle_handler = NULL, - .close_connection = NULL -}; - -const struct server_stream_ops *dcesrv_get_stream_ops(void) +/* + initialise the dcerpc server context for socket based services +*/ +static NTSTATUS dcesrv_init(struct event_context *event_context, const struct model_ops *model_ops) { - return &dcesrv_stream_ops; -} + NTSTATUS status; + struct dcesrv_context *dce_ctx; -static const struct server_service_ops dcesrv_ops = { - .name = "rpc", - .service_init = dcesrv_init, -}; + status = dcesrv_init_context(event_context, + lp_dcerpc_endpoint_servers(), + DCESRV_CALL_STATE_FLAG_MAY_ASYNC, + &dce_ctx); + NT_STATUS_NOT_OK_RETURN(status); -const struct server_service_ops *dcesrv_get_ops(void) -{ - return &dcesrv_ops; + return dcesrv_sock_init(dce_ctx, event_context, model_ops); } + NTSTATUS server_service_rpc_init(void) { - return NT_STATUS_OK; + return register_server_service("rpc", dcesrv_init); } diff --git a/source4/rpc_server/dcerpc_server.h b/source4/rpc_server/dcerpc_server.h index 2738cee040..317ebdd2ec 100644 --- a/source4/rpc_server/dcerpc_server.h +++ b/source4/rpc_server/dcerpc_server.h @@ -174,7 +174,7 @@ struct dcesrv_connection { /* the current authentication state */ struct dcesrv_auth auth_state; - struct server_connection *srv_conn; + struct stream_connection *srv_conn; /* the transport level session key */ DATA_BLOB transport_session_key; diff --git a/source4/rpc_server/dcerpc_sock.c b/source4/rpc_server/dcerpc_sock.c index 222f513bb9..ef5e7c269a 100644 --- a/source4/rpc_server/dcerpc_sock.c +++ b/source4/rpc_server/dcerpc_sock.c @@ -25,6 +25,7 @@ #include "includes.h" #include "events.h" #include "rpc_server/dcerpc_server.h" +#include "smbd/service_stream.h" struct dcesrv_socket_context { const struct dcesrv_endpoint *endpoint; @@ -50,42 +51,129 @@ static ssize_t dcerpc_write_fn(void *private, DATA_BLOB *out) static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason) { - server_terminate_connection(dce_conn->srv_conn, reason); + stream_terminate_connection(dce_conn->srv_conn, reason); } -static void add_socket_rpc_unix(struct server_service *service, struct dcesrv_endpoint *e) + +void dcesrv_sock_accept(struct stream_connection *srv_conn) { - struct dcesrv_context *dce_ctx = service->service.private_data; - struct server_stream_socket *stream_socket; - struct dcesrv_socket_context *dcesrv_sock; - uint16_t port = 1; + NTSTATUS status; + struct dcesrv_socket_context *dcesrv_sock = + talloc_get_type(srv_conn->private, struct dcesrv_socket_context); + struct dcesrv_connection *dcesrv_conn = NULL; + + status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx, + srv_conn, + dcesrv_sock->endpoint, + srv_conn, + &dcesrv_conn); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n", + nt_errstr(status))); + return; + } + + srv_conn->private = dcesrv_conn; + + return; +} + +void dcesrv_sock_recv(struct stream_connection *conn, struct timeval t, uint16_t flags) +{ + NTSTATUS status; + struct dcesrv_connection *dce_conn = talloc_get_type(conn->private, struct dcesrv_connection); + DATA_BLOB tmp_blob; + size_t nread; + + tmp_blob = data_blob_talloc(conn->socket, NULL, 0x1000); + if (tmp_blob.data == NULL) { + dcesrv_terminate_connection(dce_conn, "out of memory"); + return; + } + + status = socket_recv(conn->socket, tmp_blob.data, tmp_blob.length, &nread, 0); + if (NT_STATUS_IS_ERR(status)) { + dcesrv_terminate_connection(dce_conn, nt_errstr(status)); + return; + } + if (nread == 0) { + talloc_free(tmp_blob.data); + return; + } + + tmp_blob.length = nread; + + status = dcesrv_input(dce_conn, &tmp_blob); + talloc_free(tmp_blob.data); - stream_socket = service_setup_stream_socket(service, dcesrv_get_stream_ops(), "unix", e->ep_description.endpoint, &port); - if (!stream_socket) { - DEBUG(0,("service_setup_stream_socket(path=%s) failed\n",e->ep_description.endpoint)); + if (!NT_STATUS_IS_OK(status)) { + dcesrv_terminate_connection(dce_conn, nt_errstr(status)); return; } - dcesrv_sock = talloc(stream_socket, struct dcesrv_socket_context); - if (!dcesrv_sock) { - DEBUG(0,("talloc(stream_socket, struct dcesrv_socket_context) failed\n")); + if (dce_conn->call_list && dce_conn->call_list->replies) { + conn->event.fde->flags |= EVENT_FD_WRITE; + } +} + +void dcesrv_sock_send(struct stream_connection *conn, struct timeval t, uint16_t flags) +{ + struct dcesrv_connection *dce_conn = talloc_get_type(conn->private, struct dcesrv_connection); + NTSTATUS status; + + status = dcesrv_output(dce_conn, conn->socket, dcerpc_write_fn); + if (!NT_STATUS_IS_OK(status)) { + dcesrv_terminate_connection(dce_conn, "eof on socket"); return; } + if (!dce_conn->call_list || !dce_conn->call_list->replies) { + conn->event.fde->flags &= ~EVENT_FD_WRITE; + } +} + + +static const struct stream_server_ops dcesrv_stream_ops = { + .name = "rpc", + .accept_connection = dcesrv_sock_accept, + .recv_handler = dcesrv_sock_recv, + .send_handler = dcesrv_sock_send, +}; + + + +static NTSTATUS add_socket_rpc_unix(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e, + struct event_context *event_ctx, const struct model_ops *model_ops) +{ + struct dcesrv_socket_context *dcesrv_sock; + uint16_t port = 1; + NTSTATUS status; + + dcesrv_sock = talloc(dce_ctx, struct dcesrv_socket_context); + NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock); + /* remember the endpoint of this socket */ dcesrv_sock->endpoint = e; - dcesrv_sock->dcesrv_ctx = dce_ctx; + dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx); + + status = stream_setup_socket(event_ctx, model_ops, &dcesrv_stream_ops, + "unix", e->ep_description.endpoint, &port, + dcesrv_sock); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n", + e->ep_description.endpoint, nt_errstr(status))); + } - stream_socket->stream.private_data = dcesrv_sock; + return status; } -static void add_socket_rpc_ncalrpc(struct server_service *service, struct dcesrv_endpoint *e) +static NTSTATUS add_socket_rpc_ncalrpc(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e, + struct event_context *event_ctx, const struct model_ops *model_ops) { - struct dcesrv_context *dce_ctx = service->service.private_data; - struct server_stream_socket *stream_socket; struct dcesrv_socket_context *dcesrv_sock; uint16_t port = 1; char *full_path; + NTSTATUS status; if (!e->ep_description.endpoint) { /* No identifier specified: use DEFAULT. @@ -96,101 +184,88 @@ static void add_socket_rpc_ncalrpc(struct server_service *service, struct dcesrv full_path = talloc_asprintf(dce_ctx, "%s/%s", lp_ncalrpc_dir(), e->ep_description.endpoint); - stream_socket = service_setup_stream_socket(service, dcesrv_get_stream_ops(), "unix", full_path, &port); - if (!stream_socket) { - DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed\n",e->ep_description.endpoint, full_path)); - return; - } - - dcesrv_sock = talloc(stream_socket, struct dcesrv_socket_context); - if (!dcesrv_sock) { - DEBUG(0,("talloc(stream_socket, struct dcesrv_socket_context) failed\n")); - return; - } + dcesrv_sock = talloc(dce_ctx, struct dcesrv_socket_context); + NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock); /* remember the endpoint of this socket */ dcesrv_sock->endpoint = e; dcesrv_sock->dcesrv_ctx = dce_ctx; - stream_socket->stream.private_data = dcesrv_sock; - - return; + status = stream_setup_socket(event_ctx, model_ops, &dcesrv_stream_ops, + "unix", full_path, &port, dcesrv_sock); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n", + e->ep_description.endpoint, full_path, nt_errstr(status))); + } + return status; } /* add a socket address to the list of events, one event per dcerpc endpoint */ -static void add_socket_rpc_tcp_iface(struct server_service *service, - struct dcesrv_endpoint *e, - struct ipv4_addr *ifip) +static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e, + struct event_context *event_ctx, const struct model_ops *model_ops, + const char *address) { - struct dcesrv_context *dce_ctx = service->service.private_data; - struct server_stream_socket *stream_socket; struct dcesrv_socket_context *dcesrv_sock; uint16_t port = 0; - char *ip_str = talloc_strdup(service, sys_inet_ntoa(*ifip)); + NTSTATUS status; - if (e->ep_description.endpoint) + if (e->ep_description.endpoint) { port = atoi(e->ep_description.endpoint); - - stream_socket = service_setup_stream_socket(service, dcesrv_get_stream_ops(), "ipv4", ip_str, &port); - if (!stream_socket) { - DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed\n", ip_str, port)); - return; - } - - if (e->ep_description.endpoint == NULL) { - e->ep_description.endpoint = talloc_asprintf(dce_ctx, "%d", port); } - dcesrv_sock = talloc(stream_socket, struct dcesrv_socket_context); - if (!dcesrv_sock) { - DEBUG(0,("talloc(stream_socket, struct dcesrv_socket_context) failed\n")); - return; - } + dcesrv_sock = talloc(dce_ctx, struct dcesrv_socket_context); + NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock); /* remember the endpoint of this socket */ dcesrv_sock->endpoint = e; dcesrv_sock->dcesrv_ctx = dce_ctx; - stream_socket->stream.private_data = dcesrv_sock; + status = stream_setup_socket(event_ctx, model_ops, &dcesrv_stream_ops, + "ipv4", address, &port, dcesrv_sock); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n", + address, port, nt_errstr(status))); + } - talloc_free(ip_str); + if (e->ep_description.endpoint == NULL) { + e->ep_description.endpoint = talloc_asprintf(dce_ctx, "%d", port); + } - return; + return status; } -static void add_socket_rpc_tcp(struct server_service *service, struct dcesrv_endpoint *e) +static NTSTATUS add_socket_rpc_tcp(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e, + struct event_context *event_ctx, const struct model_ops *model_ops) { + NTSTATUS status; + /* Add TCP/IP sockets */ if (lp_interfaces() && lp_bind_interfaces_only()) { int num_interfaces = iface_count(); int i; for(i = 0; i < num_interfaces; i++) { - struct ipv4_addr *ifip = iface_n_ip(i); - if (ifip == NULL) { - continue; - } - add_socket_rpc_tcp_iface(service, e, ifip); + const char *address = sys_inet_ntoa(*iface_n_ip(i)); + status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address); + NT_STATUS_NOT_OK_RETURN(status); } } else { - struct ipv4_addr ifip; - ifip = interpret_addr2(lp_socket_address()); - add_socket_rpc_tcp_iface(service, e, &ifip); + status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, lp_socket_address()); + NT_STATUS_NOT_OK_RETURN(status); } - return; + return NT_STATUS_OK; } /**************************************************************************** Open the listening sockets for RPC over NCACN_IP_TCP/NCALRPC/NCACN_UNIX_STREAM ****************************************************************************/ -void dcesrv_sock_init(struct server_service *service) +NTSTATUS dcesrv_sock_init(struct dcesrv_context *dce_ctx, + struct event_context *event_ctx, const struct model_ops *model_ops) { - struct dcesrv_context *dce_ctx = service->service.private_data; struct dcesrv_endpoint *e; - - DEBUG(1,("dcesrv_sock_init\n")); + NTSTATUS status; /* Make sure the directory for NCALRPC exists */ if (!directory_exist(lp_ncalrpc_dir(), NULL)) { @@ -200,15 +275,18 @@ void dcesrv_sock_init(struct server_service *service) for (e=dce_ctx->endpoint_list;e;e=e->next) { switch (e->ep_description.transport) { case NCACN_UNIX_STREAM: - add_socket_rpc_unix(service, e); + status = add_socket_rpc_unix(dce_ctx, e, event_ctx, model_ops); + NT_STATUS_NOT_OK_RETURN(status); break; case NCALRPC: - add_socket_rpc_ncalrpc(service, e); + status = add_socket_rpc_ncalrpc(dce_ctx, e, event_ctx, model_ops); + NT_STATUS_NOT_OK_RETURN(status); break; case NCACN_IP_TCP: - add_socket_rpc_tcp(service, e); + status = add_socket_rpc_tcp(dce_ctx, e, event_ctx, model_ops); + NT_STATUS_NOT_OK_RETURN(status); break; default: @@ -216,89 +294,6 @@ void dcesrv_sock_init(struct server_service *service) } } - return; + return NT_STATUS_OK; } -void dcesrv_sock_accept(struct server_connection *srv_conn) -{ - NTSTATUS status; - struct dcesrv_socket_context *dcesrv_sock = srv_conn->stream_socket->stream.private_data; - struct dcesrv_connection *dcesrv_conn = NULL; - - DEBUG(5,("dcesrv_sock_accept\n")); - - status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx, - dcesrv_sock, - dcesrv_sock->endpoint, - srv_conn, - &dcesrv_conn); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n", - nt_errstr(status))); - return; - } - - srv_conn->connection.private_data = dcesrv_conn; - - return; -} - -void dcesrv_sock_recv(struct server_connection *conn, struct timeval t, uint16_t flags) -{ - NTSTATUS status; - struct dcesrv_connection *dce_conn = conn->connection.private_data; - DATA_BLOB tmp_blob; - size_t nread; - - tmp_blob = data_blob_talloc(conn->socket, NULL, 0x1000); - if (tmp_blob.data == NULL) { - dcesrv_terminate_connection(dce_conn, "out of memory"); - return; - } - - status = socket_recv(conn->socket, tmp_blob.data, tmp_blob.length, &nread, 0); - if (NT_STATUS_IS_ERR(status)) { - dcesrv_terminate_connection(dce_conn, nt_errstr(status)); - return; - } - if (nread == 0) { - talloc_free(tmp_blob.data); - return; - } - - tmp_blob.length = nread; - - status = dcesrv_input(dce_conn, &tmp_blob); - talloc_free(tmp_blob.data); - - if (!NT_STATUS_IS_OK(status)) { - dcesrv_terminate_connection(dce_conn, nt_errstr(status)); - return; - } - - if (dce_conn->call_list && dce_conn->call_list->replies) { - conn->event.fde->flags |= EVENT_FD_WRITE; - } - - return; -} - -void dcesrv_sock_send(struct server_connection *conn, struct timeval t, uint16_t flags) -{ - struct dcesrv_connection *dce_conn = conn->connection.private_data; - NTSTATUS status; - - DEBUG(10,("dcesrv_sock_send\n")); - - status = dcesrv_output(dce_conn, conn->socket, dcerpc_write_fn); - if (!NT_STATUS_IS_OK(status)) { - dcesrv_terminate_connection(dce_conn, "eof on socket"); - return; - } - - if (!dce_conn->call_list || !dce_conn->call_list->replies) { - conn->event.fde->flags &= ~EVENT_FD_WRITE; - } - - return; -} diff --git a/source4/rpc_server/epmapper/rpc_epmapper.c b/source4/rpc_server/epmapper/rpc_epmapper.c index 797dcc624e..eb9598b6be 100644 --- a/source4/rpc_server/epmapper/rpc_epmapper.c +++ b/source4/rpc_server/epmapper/rpc_epmapper.c @@ -217,10 +217,11 @@ static error_status_t epm_Map(struct dcesrv_call_state *dce_call, TALLOC_CTX *me transport = dcerpc_transport_by_tower(&r->in.map_tower->tower); if (transport == -1) { - DEBUG(1, ("Client requested unknown transport with levels: ")); + DEBUG(2, ("Client requested unknown transport with levels: ")); for (i = 2; i < r->in.map_tower->tower.num_floors; i++) { - DEBUG(1, ("%d, ", r->in.map_tower->tower.floors[i].lhs.protocol)); + DEBUG(2, ("%d, ", r->in.map_tower->tower.floors[i].lhs.protocol)); } + DEBUG(2, ("\n")); goto failed; } -- cgit