From: Samuel Cabrero Date: Wed, 27 Feb 2019 16:52:21 +0000 (+0100) Subject: s3:rpc_server: Setup ncacn_ip_tcp sockets through endpoint init X-Git-Tag: ldb-2.2.0~1332 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a18163a147bcbda2868e556e0a88b1f46fe31e1d;p=thirdparty%2Fsamba.git s3:rpc_server: Setup ncacn_ip_tcp sockets through endpoint init The listener is created in the endpoint memory context. If the endpoint is freed, the listener will be freed too and the socket closed. Signed-off-by: Samuel Cabrero Reviewed-by: Andrew Bartlett --- diff --git a/source3/rpc_server/epmd.c b/source3/rpc_server/epmd.c index 148a7e4655d..baf99db5f60 100644 --- a/source3/rpc_server/epmd.c +++ b/source3/rpc_server/epmd.c @@ -238,16 +238,6 @@ void start_epmd(struct tevent_context *ev_ctx, } } - status = dcesrv_setup_ncacn_ip_tcp_sockets(ev_ctx, - msg_ctx, - &ndr_table_epmapper, - NULL, - 135); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Failed to open epmd tcpip sockets!\n")); - exit(1); - } - status = dcesrv_setup_ncalrpc_socket(ev_ctx, msg_ctx, "EPMAPPER", diff --git a/source3/rpc_server/rpc_server.c b/source3/rpc_server/rpc_server.c index ca6f61c332f..2ba8cc0b53e 100644 --- a/source3/rpc_server/rpc_server.c +++ b/source3/rpc_server/rpc_server.c @@ -93,6 +93,8 @@ struct dcerpc_ncacn_listen_state { struct tevent_context *ev_ctx; struct messaging_context *msg_ctx; + struct dcesrv_context *dce_ctx; + struct dcesrv_endpoint *endpoint; dcerpc_ncacn_termination_fn termination_fn; void *termination_data; }; @@ -308,32 +310,48 @@ NTSTATUS dcesrv_create_ncacn_ip_tcp_socket(const struct sockaddr_storage *ifss, NTSTATUS dcesrv_setup_ncacn_ip_tcp_socket(struct tevent_context *ev_ctx, struct messaging_context *msg_ctx, + struct dcesrv_context *dce_ctx, + struct dcesrv_endpoint *e, const struct sockaddr_storage *ifss, - uint16_t *port) + dcerpc_ncacn_termination_fn term_fn, + void *term_data) { - struct dcerpc_ncacn_listen_state *state; - struct tevent_fd *fde; + struct dcerpc_ncacn_listen_state *state = NULL; + struct tevent_fd *fde = NULL; + const char *endpoint = NULL; + uint16_t port = 0; + char port_str[6]; int rc; NTSTATUS status; - state = talloc_zero(ev_ctx, struct dcerpc_ncacn_listen_state); + endpoint = dcerpc_binding_get_string_option(e->ep_description, + "endpoint"); + if (endpoint != NULL) { + port = atoi(endpoint); + } + + /* Alloc in endpoint context. If the endpoint is freed (for example + * when forked daemons reinit the dcesrv_context, the tevent_fd + * listener will be stopped and the socket closed */ + state = talloc_zero(e, struct dcerpc_ncacn_listen_state); if (state == NULL) { DBG_ERR("Out of memory\n"); return NT_STATUS_NO_MEMORY; } state->fd = -1; - state->ep.port = *port; + state->ev_ctx = ev_ctx; + state->msg_ctx = msg_ctx; + state->endpoint = e; + state->dce_ctx = talloc_reference(state, dce_ctx); + state->termination_fn = term_fn; + state->termination_data = term_data; - status = dcesrv_create_ncacn_ip_tcp_socket(ifss, &state->ep.port, - &state->fd); + status = dcesrv_create_ncacn_ip_tcp_socket(ifss, &port, &state->fd); if (!NT_STATUS_IS_OK(status)) { goto out; } - state->ev_ctx = ev_ctx; - state->msg_ctx = msg_ctx; - /* ready to listen */ set_socket_options(state->fd, "SO_KEEPALIVE"); set_socket_options(state->fd, lp_socket_options()); @@ -350,7 +368,7 @@ NTSTATUS dcesrv_setup_ncacn_ip_tcp_socket(struct tevent_context *ev_ctx, } DBG_DEBUG("Opened socket fd %d for port %u\n", - state->fd, state->ep.port); + state->fd, port); errno = 0; fde = tevent_add_fd(state->ev_ctx, @@ -371,7 +389,16 @@ NTSTATUS dcesrv_setup_ncacn_ip_tcp_socket(struct tevent_context *ev_ctx, tevent_fd_set_auto_close(fde); - *port = state->ep.port; + /* Set the port in the endpoint */ + snprintf(port_str, sizeof(port_str), "%u", port); + + status = dcerpc_binding_set_string_option(e->ep_description, + "endpoint", port_str); + if (!NT_STATUS_IS_OK(status)) { + DBG_ERR("Failed to set binding endpoint '%s': %s\n", + port_str, nt_errstr(status)); + goto out; + } return NT_STATUS_OK; diff --git a/source3/rpc_server/rpc_server.h b/source3/rpc_server/rpc_server.h index 8d96198067e..68fff9563a1 100644 --- a/source3/rpc_server/rpc_server.h +++ b/source3/rpc_server/rpc_server.h @@ -87,8 +87,11 @@ NTSTATUS dcesrv_create_ncacn_ip_tcp_socket(const struct sockaddr_storage *ifss, int *out_fd); NTSTATUS dcesrv_setup_ncacn_ip_tcp_socket(struct tevent_context *ev_ctx, struct messaging_context *msg_ctx, + struct dcesrv_context *dce_ctx, + struct dcesrv_endpoint *e, const struct sockaddr_storage *ifss, - uint16_t *port); + dcerpc_ncacn_termination_fn term_fn, + void *term_data); NTSTATUS dcesrv_create_ncalrpc_socket(const char *name, int *out_fd); NTSTATUS dcesrv_setup_ncalrpc_socket(struct tevent_context *ev_ctx, diff --git a/source3/rpc_server/rpc_service_setup.c b/source3/rpc_server/rpc_service_setup.c index 4eebb280eb2..311654bf4cd 100644 --- a/source3/rpc_server/rpc_service_setup.c +++ b/source3/rpc_server/rpc_service_setup.c @@ -213,8 +213,13 @@ NTSTATUS dcesrv_setup_endpoint_sockets(struct tevent_context *ev_ctx, break; case NCACN_IP_TCP: - /* TODO */ - status = NT_STATUS_OK; + status = dcesrv_setup_ncacn_ip_tcp_sockets(ev_ctx, + msg_ctx, + dce_ctx, + e, + bvec, + term_fn, + term_data); break; case NCACN_NP: diff --git a/source3/rpc_server/rpc_sock_helper.c b/source3/rpc_server/rpc_sock_helper.c index 069d0959534..5ca154bf5ad 100644 --- a/source3/rpc_server/rpc_sock_helper.c +++ b/source3/rpc_server/rpc_sock_helper.c @@ -27,6 +27,7 @@ #include "rpc_server/rpc_server.h" #include "rpc_server/rpc_sock_helper.h" #include "lib/server_prefork.h" +#include "librpc/ndr/ndr_table.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV @@ -158,16 +159,15 @@ done: } NTSTATUS dcesrv_setup_ncacn_ip_tcp_sockets(struct tevent_context *ev_ctx, - struct messaging_context *msg_ctx, - const struct ndr_interface_table *iface, - struct dcerpc_binding_vector *bvec, - uint16_t port) + struct messaging_context *msg_ctx, + struct dcesrv_context *dce_ctx, + struct dcesrv_endpoint *e, + struct dcerpc_binding_vector *bvec, + dcerpc_ncacn_termination_fn t_fn, + void *t_data) { - uint32_t num_ifs = iface_count(); - uint32_t i; - uint16_t p = port; TALLOC_CTX *tmp_ctx; - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + NTSTATUS status; int rc; tmp_ctx = talloc_stackframe(); @@ -176,6 +176,9 @@ NTSTATUS dcesrv_setup_ncacn_ip_tcp_sockets(struct tevent_context *ev_ctx, } if (lp_interfaces() && lp_bind_interfaces_only()) { + uint32_t num_ifs = iface_count(); + uint32_t i; + /* * We have been given an interfaces line, and been told to only * bind to those interfaces. Create a socket per interface and @@ -188,16 +191,23 @@ NTSTATUS dcesrv_setup_ncacn_ip_tcp_sockets(struct tevent_context *ev_ctx, iface_n_sockaddr_storage(i); struct tsocket_address *bind_addr; const char *addr; + const char *endpoint; + uint16_t port = 0; status = dcesrv_setup_ncacn_ip_tcp_socket(ev_ctx, msg_ctx, + dce_ctx, + e, ifss, - &p); + t_fn, + t_data); if (!NT_STATUS_IS_OK(status)) { goto done; } if (bvec != NULL) { + struct dcesrv_if_list *if_list = NULL; + rc = tsocket_address_bsd_from_sockaddr(tmp_ctx, (const struct sockaddr*)ifss, sizeof(struct sockaddr_storage), @@ -214,12 +224,24 @@ NTSTATUS dcesrv_setup_ncacn_ip_tcp_sockets(struct tevent_context *ev_ctx, goto done; } - status = dcerpc_binding_vector_add_port(iface, - bvec, - addr, - p); - if (!NT_STATUS_IS_OK(status)) { - goto done; + endpoint = dcerpc_binding_get_string_option(e->ep_description, + "endpoint"); + if (endpoint != NULL) { + port = atoi(endpoint); + } + + for (if_list = e->interface_list; if_list; if_list = if_list->next) { + const struct ndr_interface_table *iface = NULL; + iface = ndr_table_by_syntax(&if_list->iface->syntax_id); + if (iface != NULL) { + status = dcerpc_binding_vector_add_port(iface, + bvec, + addr, + port); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + } } } } @@ -248,19 +270,38 @@ NTSTATUS dcesrv_setup_ncacn_ip_tcp_sockets(struct tevent_context *ev_ctx, status = dcesrv_setup_ncacn_ip_tcp_socket(ev_ctx, msg_ctx, + dce_ctx, + e, &ss, - &p); + t_fn, + t_data); if (!NT_STATUS_IS_OK(status)) { goto done; } if (bvec != NULL) { - status = dcerpc_binding_vector_add_port(iface, - bvec, - sock_tok, - p); - if (!NT_STATUS_IS_OK(status)) { - goto done; + struct dcesrv_if_list *if_list = NULL; + const char *endpoint; + uint16_t port = 0; + + endpoint = dcerpc_binding_get_string_option(e->ep_description, + "endpoint"); + if (endpoint != NULL) { + port = atoi(endpoint); + } + + for (if_list = e->interface_list; if_list; if_list = if_list->next) { + const struct ndr_interface_table *iface = NULL; + iface = ndr_table_by_syntax(&if_list->iface->syntax_id); + if (iface != NULL) { + status = dcerpc_binding_vector_add_port(iface, + bvec, + sock_tok, + port); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + } } } } diff --git a/source3/rpc_server/rpc_sock_helper.h b/source3/rpc_server/rpc_sock_helper.h index 4aca3411de6..1bf1be4c0e4 100644 --- a/source3/rpc_server/rpc_sock_helper.h +++ b/source3/rpc_server/rpc_sock_helper.h @@ -23,6 +23,8 @@ #ifndef _RPC_SOCK_HELPER_H_ #define _RPC_SOCK_HELPER_H_ +#include "rpc_server.h" + struct pf_listen_fd; NTSTATUS dcesrv_create_ncacn_ip_tcp_sockets( @@ -33,10 +35,12 @@ NTSTATUS dcesrv_create_ncacn_ip_tcp_sockets( int *listen_fd_size); NTSTATUS dcesrv_setup_ncacn_ip_tcp_sockets(struct tevent_context *ev_ctx, - struct messaging_context *msg_ctx, - const struct ndr_interface_table *iface, - struct dcerpc_binding_vector *bvec, - uint16_t port); + struct messaging_context *msg_ctx, + struct dcesrv_context *dce_ctx, + struct dcesrv_endpoint *e, + struct dcerpc_binding_vector *bvec, + dcerpc_ncacn_termination_fn t_fn, + void *t_data); #endif /* _RPC_SOCK_HELPER_H_ */