summaryrefslogtreecommitdiff
path: root/source3/rpc_server/rpc_sock_helper.c
diff options
context:
space:
mode:
authorAndreas Schneider <asn@samba.org>2011-06-30 10:46:48 +0200
committerAndreas Schneider <asn@samba.org>2011-08-01 08:50:35 +0200
commit498e53c22008c918e2ae5ca8126a8b1b2e8322df (patch)
tree1cab0c24ed4f6f2dfc89082e3fc08d90b6c2ee4f /source3/rpc_server/rpc_sock_helper.c
parent02cdb65fc67954e3811349021563f496fc282f7b (diff)
downloadsamba-498e53c22008c918e2ae5ca8126a8b1b2e8322df.tar.gz
samba-498e53c22008c918e2ae5ca8126a8b1b2e8322df.tar.bz2
samba-498e53c22008c918e2ae5ca8126a8b1b2e8322df.zip
s3-rpc_server: Add RPC socket helper functions.
Diffstat (limited to 'source3/rpc_server/rpc_sock_helper.c')
-rw-r--r--source3/rpc_server/rpc_sock_helper.c271
1 files changed, 271 insertions, 0 deletions
diff --git a/source3/rpc_server/rpc_sock_helper.c b/source3/rpc_server/rpc_sock_helper.c
new file mode 100644
index 0000000000..c767cd817d
--- /dev/null
+++ b/source3/rpc_server/rpc_sock_helper.c
@@ -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: */