s3-rpc_server: Add RPC socket helper functions.
authorAndreas Schneider <asn@samba.org>
Thu, 30 Jun 2011 08:46:48 +0000 (10:46 +0200)
committerAndreas Schneider <asn@samba.org>
Mon, 1 Aug 2011 06:50:35 +0000 (08:50 +0200)
source3/Makefile.in
source3/rpc_server/rpc_sock_helper.c [new file with mode: 0644]
source3/rpc_server/rpc_sock_helper.h [new file with mode: 0644]

index 67d5d2de713a983146ca21412f78a6c893da358e..f1fe0dd0619cf29992926886bd28b7f454d31956 100644 (file)
@@ -765,6 +765,7 @@ RPC_SERVER_OBJ = $(RPC_LSARPC_OBJ) $(RPC_WINREG_OBJ) $(RPC_INITSHUTDOWN_OBJ) \
                 $(LIBCLI_NETLOGON_OBJ) \
                 $(RPC_SERVER_REGISTER_OBJ) \
                 $(RPC_CLIENT_SCHANNEL_OBJ) \
+                rpc_server/rpc_sock_helper.o \
                 rpc_server/rpc_service_setup.o \
                 rpc_client/init_netlogon.o \
                 rpc_client/init_samr.o
diff --git a/source3/rpc_server/rpc_sock_helper.c b/source3/rpc_server/rpc_sock_helper.c
new file mode 100644 (file)
index 0000000..c767cd8
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *
+ *  RPC Socket Helper
+ *
+ *  Copyright (c) 2011      Andreas Schneider <asn@samba.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "ntdomain.h"
+
+#include "../lib/tsocket/tsocket.h"
+#include "librpc/rpc/dcerpc_ep.h"
+#include "rpc_server/rpc_server.h"
+#include "rpc_server/rpc_sock_helper.h"
+
+NTSTATUS rpc_create_tcpip_sockets(const struct ndr_interface_table *iface,
+                                 struct dcerpc_binding_vector *bvec,
+                                 uint16_t port,
+                                 int *listen_fd,
+                                 int *listen_fd_size)
+{
+       uint32_t num_ifs = iface_count();
+       uint32_t i;
+       uint16_t p = port;
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       int rc;
+
+       tmp_ctx = talloc_stackframe();
+       if (tmp_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (lp_interfaces() && lp_bind_interfaces_only()) {
+               /*
+                * 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.
+                */
+
+               /* Now open a listen socket for each of the interfaces. */
+               for (i = 0; i < num_ifs; i++) {
+                       const struct sockaddr_storage *ifss =
+                                       iface_n_sockaddr_storage(i);
+                       struct tsocket_address *bind_addr;
+                       const char *addr;
+                       int fd;
+
+                       fd = create_tcpip_socket(ifss, &p);
+                       if (fd < 0 || p == 0) {
+                               status = NT_STATUS_UNSUCCESSFUL;
+                               goto done;
+                       }
+                       listen_fd[*listen_fd_size] = fd;
+                       (*listen_fd_size)++;
+
+                       if (bvec != NULL) {
+                               rc = tsocket_address_bsd_from_sockaddr(tmp_ctx,
+                                                                      (struct sockaddr *)ifss,
+                                                                      sizeof(struct sockaddr_storage),
+                                                                      &bind_addr);
+                               if (rc < 0) {
+                                       close(fd);
+                                       status = NT_STATUS_NO_MEMORY;
+                                       goto done;
+                               }
+
+                               addr = tsocket_address_inet_addr_string(bind_addr,
+                                                                       tmp_ctx);
+                               if (addr == NULL) {
+                                       close(fd);
+                                       status = NT_STATUS_NO_MEMORY;
+                                       goto done;
+                               }
+
+                               status = dcerpc_binding_vector_add_port(iface,
+                                                                       bvec,
+                                                                       addr,
+                                                                       p);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       close(fd);
+                                       goto done;
+                               }
+                       }
+               }
+       } else {
+               const char *sock_addr = lp_socket_address();
+               const char *sock_ptr;
+               char *sock_tok;
+
+               if (strequal(sock_addr, "0.0.0.0") ||
+                   strequal(sock_addr, "::")) {
+#if HAVE_IPV6
+                       sock_addr = "::,0.0.0.0";
+#else
+                       sock_addr = "0.0.0.0";
+#endif
+               }
+
+               for (sock_ptr = sock_addr;
+                    next_token_talloc(talloc_tos(), &sock_ptr, &sock_tok, " \t,");
+                   ) {
+                       struct sockaddr_storage ss;
+                       int fd;
+
+                       /* open an incoming socket */
+                       if (!interpret_string_addr(&ss,
+                                                  sock_tok,
+                                                  AI_NUMERICHOST|AI_PASSIVE)) {
+                               continue;
+                       }
+
+                       fd = create_tcpip_socket(&ss, &p);
+                       if (fd < 0 || p == 0) {
+                               status = NT_STATUS_UNSUCCESSFUL;
+                               goto done;
+                       }
+                       listen_fd[*listen_fd_size] = fd;
+                       (*listen_fd_size)++;
+
+                       if (bvec != NULL) {
+                               status = dcerpc_binding_vector_add_port(iface,
+                                                                       bvec,
+                                                                       sock_ptr,
+                                                                       p);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       close(fd);
+                                       return status;
+                               }
+                       }
+               }
+       }
+
+       status = NT_STATUS_OK;
+done:
+       talloc_free(tmp_ctx);
+       return status;
+}
+
+NTSTATUS rpc_setup_tcpip_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)
+{
+       uint32_t num_ifs = iface_count();
+       uint32_t i;
+       uint16_t p = 0;
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       int rc;
+
+       tmp_ctx = talloc_stackframe();
+       if (tmp_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (lp_interfaces() && lp_bind_interfaces_only()) {
+               /*
+                * 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.
+                */
+
+               /* Now open a listen socket for each of the interfaces. */
+               for (i = 0; i < num_ifs; i++) {
+                       const struct sockaddr_storage *ifss =
+                                       iface_n_sockaddr_storage(i);
+                       struct tsocket_address *bind_addr;
+                       const char *addr;
+
+                       p = setup_dcerpc_ncacn_tcpip_socket(ev_ctx,
+                                                           msg_ctx,
+                                                           ifss,
+                                                           port);
+                       if (p == 0) {
+                               status = NT_STATUS_UNSUCCESSFUL;
+                               goto done;
+                       }
+
+                       if (bvec != NULL) {
+                               rc = tsocket_address_bsd_from_sockaddr(tmp_ctx,
+                                                                      (struct sockaddr*)ifss,
+                                                                      sizeof(struct sockaddr_storage),
+                                                                      &bind_addr);
+                               if (rc < 0) {
+                                       return NT_STATUS_NO_MEMORY;
+                               }
+
+                               addr = tsocket_address_inet_addr_string(bind_addr,
+                                                                       tmp_ctx);
+                               if (addr == NULL) {
+                                       return NT_STATUS_NO_MEMORY;
+                               }
+
+                               status = dcerpc_binding_vector_add_port(iface,
+                                                                       bvec,
+                                                                       addr,
+                                                                       p);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       return status;
+                               }
+                       }
+               }
+       } else {
+               const char *sock_addr = lp_socket_address();
+               const char *sock_ptr;
+               char *sock_tok;
+
+               if (strequal(sock_addr, "0.0.0.0") ||
+                   strequal(sock_addr, "::")) {
+#if HAVE_IPV6
+                       sock_addr = "::,0.0.0.0";
+#else
+                       sock_addr = "0.0.0.0";
+#endif
+               }
+
+               for (sock_ptr = sock_addr;
+                    next_token_talloc(talloc_tos(), &sock_ptr, &sock_tok, " \t,");
+                   ) {
+                       struct sockaddr_storage ss;
+
+                       /* open an incoming socket */
+                       if (!interpret_string_addr(&ss,
+                                                  sock_tok,
+                                                  AI_NUMERICHOST|AI_PASSIVE)) {
+                               continue;
+                       }
+
+                       p = setup_dcerpc_ncacn_tcpip_socket(ev_ctx,
+                                                           msg_ctx,
+                                                           &ss,
+                                                           port);
+                       if (p == 0) {
+                               return NT_STATUS_UNSUCCESSFUL;
+                       }
+
+                       if (bvec != NULL) {
+                               status = dcerpc_binding_vector_add_port(iface,
+                                                                       bvec,
+                                                                       sock_tok,
+                                                                       p);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       return status;
+                               }
+                       }
+               }
+       }
+
+       status = NT_STATUS_OK;
+done:
+       talloc_free(tmp_ctx);
+       return status;
+}
+
+/* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */
diff --git a/source3/rpc_server/rpc_sock_helper.h b/source3/rpc_server/rpc_sock_helper.h
new file mode 100644 (file)
index 0000000..0590d1f
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *
+ *  RPC Socket Helper
+ *
+ *  Copyright (c) 2011      Andreas Schneider <asn@samba.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _RPC_SOCK_HELPER_H_
+#define _RPC_SOCK_HELPER_H_
+
+NTSTATUS rpc_create_tcpip_sockets(const struct ndr_interface_table *iface,
+                                 struct dcerpc_binding_vector *bvec,
+                                 uint16_t port,
+                                 int *listen_fd,
+                                 int *listen_fd_size);
+
+NTSTATUS rpc_setup_tcpip_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);
+
+#endif /* _RPC_SOCK_HELPER_H_ */
+
+/* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */