]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
rpc_server: Factor out dcesrv_open_ncacn_ip_tcp_sockets()
authorVolker Lendecke <vl@samba.org>
Thu, 31 Dec 2020 08:21:25 +0000 (09:21 +0100)
committerVolker Lendecke <vl@samba.org>
Mon, 11 Jan 2021 13:19:32 +0000 (13:19 +0000)
The main change is to return an allocated array of file descriptors in
dcesrv_open_ncacn_ip_tcp_sockets() instead of filling a preallocated
array of pf_listen_fd structures.

Signed-off-by: Volker Lendecke <vl@samba.org>
source3/rpc_server/rpc_sock_helper.c

index 28f319868fa9964747bb65613ae9fcb5080bafd8..d0c9bbe2eb5c556a1b61fe335db926959f2ca7d6 100644 (file)
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
 
-NTSTATUS dcesrv_create_ncacn_ip_tcp_sockets(struct dcesrv_endpoint *e,
-                                           struct pf_listen_fd *listen_fd,
-                                           int *listen_fd_size)
+static NTSTATUS dcesrv_open_ncacn_ip_tcp_sockets(
+       struct dcesrv_endpoint *e,
+       TALLOC_CTX *mem_ctx,
+       size_t *pnum_fds,
+       int **pfds)
 {
-       TALLOC_CTX *tmp_ctx;
-       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
        uint16_t port = 0;
        char port_str[6];
        const char *endpoint = NULL;
+       size_t i = 0, num_fds;
+       int *fds = NULL;
+       struct samba_sockaddr *addrs = NULL;
+       NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
+       bool ok;
 
-       tmp_ctx = talloc_stackframe();
-       if (tmp_ctx == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       endpoint = dcerpc_binding_get_string_option(e->ep_description,
-                                                   "endpoint");
+       endpoint = dcerpc_binding_get_string_option(
+               e->ep_description, "endpoint");
        if (endpoint != NULL) {
                port = atoi(endpoint);
        }
 
        if (lp_interfaces() && lp_bind_interfaces_only()) {
-               uint32_t num_ifs = iface_count();
-               uint32_t i;
+               num_fds = iface_count();
+       } else {
+               num_fds = 1;
+#ifdef HAVE_IPV6
+               num_fds += 1;
+#endif
+       }
 
-               /*
-                * We have been given an interfaces line, and been told to only
-                * bind to those interfaces. Create a socket per interface and
-                * bind to only these.
-                */
+       addrs = talloc_array(mem_ctx, struct samba_sockaddr, num_fds);
+       if (addrs == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto fail;
+       }
+       fds = talloc_array(mem_ctx, int, num_fds);
+       if (fds == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto fail;
+       }
 
-               /* Now open a listen socket for each of the interfaces. */
-               for (i = 0; i < num_ifs; i++) {
+       /*
+        * Fill "addrs"
+        */
+
+       if (lp_interfaces() && lp_bind_interfaces_only()) {
+               for (i=0; i<num_fds; i++) {
                        const struct sockaddr_storage *ifss =
-                                       iface_n_sockaddr_storage(i);
-                       int fd = -1;
+                               iface_n_sockaddr_storage(i);
 
-                       status = dcesrv_create_ncacn_ip_tcp_socket(ifss,
-                                                                  &port,
-                                                                  &fd);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               goto done;
+                       ok = sockaddr_storage_to_samba_sockaddr(
+                               &addrs[i], ifss);
+                       if (!ok) {
+                               i = 0; /* nothing to close */
+                               goto fail;
                        }
-                       listen_fd[*listen_fd_size].fd = fd;
-                       listen_fd[*listen_fd_size].fd_data = e;
-                       (*listen_fd_size)++;
                }
        } else {
-               const char *sock_addr;
-               const char *sock_ptr;
-               char *sock_tok;
+               struct sockaddr_storage ss = { .ss_family = 0 };
 
 #ifdef HAVE_IPV6
-               sock_addr = "::,0.0.0.0";
-#else
-               sock_addr = "0.0.0.0";
+               ok = interpret_string_addr(
+                       &ss, "::", AI_NUMERICHOST|AI_PASSIVE);
+               if (!ok) {
+                       goto fail;
+               }
+               ok = sockaddr_storage_to_samba_sockaddr(&addrs[0], &ss);
+               if (!ok) {
+                       goto fail;
+               }
 #endif
+               ok = interpret_string_addr(
+                       &ss, "0.0.0.0", AI_NUMERICHOST|AI_PASSIVE);
+               if (!ok) {
+                       goto fail;
+               }
 
-               for (sock_ptr = sock_addr;
-                    next_token_talloc(talloc_tos(), &sock_ptr, &sock_tok, " \t,");
-                   ) {
-                       struct sockaddr_storage ss;
-                       int fd = -1;
-
-                       /* open an incoming socket */
-                       if (!interpret_string_addr(&ss,
-                                                  sock_tok,
-                                                  AI_NUMERICHOST|AI_PASSIVE)) {
-                               continue;
-                       }
+               /* num_fds set above depending on HAVE_IPV6 */
+               ok = sockaddr_storage_to_samba_sockaddr(
+                       &addrs[num_fds-1], &ss);
+               if (!ok) {
+                       goto fail;
+               }
+       }
 
-                       status = dcesrv_create_ncacn_ip_tcp_socket(&ss,
-                                                                  &port,
-                                                                  &fd);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               goto done;
-                       }
-                       listen_fd[*listen_fd_size].fd = fd;
-                       listen_fd[*listen_fd_size].fd_data = e;
-                       (*listen_fd_size)++;
+       for (i=0; i<num_fds; i++) {
+               status = dcesrv_create_ncacn_ip_tcp_socket(
+                       &addrs[i].u.ss, &port, &fds[i]);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto fail;
                }
+               samba_sockaddr_set_port(&addrs[i], 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);
+       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 fail;
+       }
+
+       TALLOC_FREE(addrs);
+
+       *pfds = fds;
+       *pnum_fds = num_fds;
+
+       return NT_STATUS_OK;
+
+fail:
+       while (i > 0) {
+               close(fds[i-1]);
+               i -= 1;
+       }
+       TALLOC_FREE(fds);
+       TALLOC_FREE(addrs);
+       return status;
+}
+
+NTSTATUS dcesrv_create_ncacn_ip_tcp_sockets(struct dcesrv_endpoint *e,
+                                           struct pf_listen_fd *listen_fd,
+                                           int *listen_fd_size)
+{
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       int *fds = NULL;
+       size_t i, num_fds = 0;
+
+       tmp_ctx = talloc_stackframe();
+       if (tmp_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       status = dcesrv_open_ncacn_ip_tcp_sockets(e, tmp_ctx, &num_fds, &fds);
+       if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
 
+       for (i=0; i<num_fds; i++) {
+               listen_fd[*listen_fd_size].fd = fds[i];
+               listen_fd[*listen_fd_size].fd_data = e;
+               *listen_fd_size += 1;
+       }
+
        status = NT_STATUS_OK;
 done:
        talloc_free(tmp_ctx);