r2328: add the start of a new system and protocol
authorStefan Metzmacher <metze@samba.org>
Mon, 13 Sep 2004 14:17:41 +0000 (14:17 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:58:44 +0000 (12:58 -0500)
independent socket library.

this is not used, but compiled currently

there're maybe some api changes later...

metze
(This used to be commit de4447d7a57c614b80d0ac00dca900ea7e1c21ea)

source4/configure.in
source4/include/includes.h
source4/lib/socket/config.m4 [new file with mode: 0644]
source4/lib/socket/config.mk [new file with mode: 0644]
source4/lib/socket/socket.c [new file with mode: 0644]
source4/lib/socket/socket.h [new file with mode: 0644]
source4/lib/socket/socket_ipv4.c [new file with mode: 0644]
source4/libcli/libsmb.m4

index eccdc1be6ebc46f561ad27fd6fc8b1a74b7ffb67..6bd8f9323c3eb0cca4381272b7455d4f99f36b70 100644 (file)
@@ -14,6 +14,7 @@ SMB_INCLUDE_M4(build/m4/rewrite.m4)
 SMB_INCLUDE_M4(lib/popt/config.m4)
 SMB_INCLUDE_M4(lib/iconv.m4)
 SMB_INCLUDE_M4(lib/basic.m4)
+SMB_INCLUDE_M4(lib/socket/config.m4)
 SMB_INCLUDE_M4(lib/tdb/config.m4)
 SMB_INCLUDE_M4(lib/ldb/config.m4)
 SMB_INCLUDE_M4(lib/cmdline/config.m4)
index 33806ab36f97a87c0521435085dc0c87282e7dcf..b033d584f857c0fee6717c47298bbdfcf41bde79 100644 (file)
@@ -632,6 +632,7 @@ extern int errno;
 #include "rewrite.h"
 #include "smb.h"
 #include "ads.h"
+#include "lib/socket/socket.h"
 #include "libcli/ldap/ldap.h"
 #include "nameserv.h"
 #include "secrets.h"
diff --git a/source4/lib/socket/config.m4 b/source4/lib/socket/config.m4
new file mode 100644 (file)
index 0000000..a5d3d09
--- /dev/null
@@ -0,0 +1,4 @@
+
+SMB_MODULE_MK(socket_ipv4,SOCKET,STATIC,lib/socket/config.mk)
+
+SMB_SUBSYSTEM_MK(SOCKET,lib/socket/config.mk)
diff --git a/source4/lib/socket/config.mk b/source4/lib/socket/config.mk
new file mode 100644 (file)
index 0000000..854702a
--- /dev/null
@@ -0,0 +1,16 @@
+
+################################################
+# Start MODULE socket_ipv4
+[MODULE::socket_ipv4]
+INIT_OBJ_FILES = \
+               lib/socket/socket_ipv4.o
+# End MODULE socket_ipv4
+################################################
+
+################################################
+# Start SUBSYSTEM SOCKET
+[SUBSYSTEM::SOCKET]
+INIT_OBJ_FILES = \
+               lib/socket/socket.o
+# End SUBSYSTEM SOCKET
+################################################
diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c
new file mode 100644 (file)
index 0000000..fefd7a1
--- /dev/null
@@ -0,0 +1,215 @@
+/* 
+   Unix SMB/CIFS implementation.
+   Socket functions
+   Copyright (C) Stefan Metzmacher 2004
+   
+   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 2 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, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+NTSTATUS socket_create(const char *name, enum socket_type type, struct socket_context **new_sock, uint32_t flags)
+{
+       NTSTATUS status;
+
+       (*new_sock) = talloc_p(NULL, struct socket_context);
+       if (!(*new_sock)) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       (*new_sock)->type = type;
+       (*new_sock)->state = SOCKET_STATE_UNDEFINED;
+       (*new_sock)->flags = flags;
+
+       (*new_sock)->fd = -1;
+
+       (*new_sock)->private_data = NULL;
+       (*new_sock)->ops = socket_getops_byname(name, type);
+       if (!(*new_sock)->ops) {
+               talloc_free((*new_sock));
+               return status;
+       }
+
+       status = (*new_sock)->ops->init((*new_sock));
+       if (!NT_STATUS_IS_OK(status)) {
+               talloc_free((*new_sock));
+               return status;
+       }
+
+       return NT_STATUS_OK;
+}
+
+void socket_destroy(struct socket_context *sock)
+{
+       if (sock->ops->close) {
+               sock->ops->close(sock);
+       }
+       talloc_free(sock);
+}
+
+NTSTATUS socket_connect(struct socket_context *sock,
+                       const char *my_address, int my_port,
+                       const char *server_address, int server_port,
+                       uint32_t flags)
+{
+       if (sock->type != SOCKET_TYPE_STREAM) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (sock->state != SOCKET_STATE_UNDEFINED) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (!sock->ops->connect) {
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+
+       return sock->ops->connect(sock, my_address, my_port, server_address, server_port, flags);
+}
+
+NTSTATUS socket_listen(struct socket_context *sock, const char *my_address, int port, int queue_size, uint32_t flags)
+{
+       if (sock->type != SOCKET_TYPE_STREAM) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (sock->state != SOCKET_STATE_UNDEFINED) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (!sock->ops->listen) {
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+
+       return sock->ops->listen(sock, my_address, port, queue_size, flags);
+}
+
+NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_sock, uint32_t flags)
+{
+       if (sock->type != SOCKET_TYPE_STREAM) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (sock->state != SOCKET_STATE_SERVER_LISTEN) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (!sock->ops->accept) {
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+
+       return sock->ops->accept(sock, new_sock, flags);
+}
+
+NTSTATUS socket_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx,
+                       DATA_BLOB *blob, size_t wantlen, uint32_t flags)
+{
+       if (sock->type != SOCKET_TYPE_STREAM) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (sock->state != SOCKET_STATE_CLIENT_CONNECTED ||
+           sock->state != SOCKET_STATE_SERVER_CONNECTED) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (!sock->ops->recv) {
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+
+       return sock->ops->recv(sock, mem_ctx, blob, wantlen, flags);
+}
+
+NTSTATUS socket_send(struct socket_context *sock, TALLOC_CTX *mem_ctx,
+                       const DATA_BLOB *blob, size_t *sendlen, uint32_t flags)
+{
+       if (sock->type != SOCKET_TYPE_STREAM) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (sock->state != SOCKET_STATE_CLIENT_CONNECTED ||
+           sock->state != SOCKET_STATE_SERVER_CONNECTED) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (!sock->ops->send) {
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+
+       return sock->ops->send(sock, mem_ctx, blob, sendlen, flags);
+}
+
+NTSTATUS socket_set_option(struct socket_context *sock, const char *option, const char *val)
+{
+       if (!sock->ops->set_option) {
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+
+       return sock->ops->set_option(sock, option, val);
+}
+
+const char *socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
+{
+       if (!sock->ops->get_peer_addr) {
+               return NULL;
+       }
+
+       return sock->ops->get_peer_addr(sock, mem_ctx);
+}
+
+int socket_get_peer_port(struct socket_context *sock, TALLOC_CTX *mem_ctx)
+{
+       if (!sock->ops->get_peer_port) {
+               return -1;
+       }
+
+       return sock->ops->get_peer_port(sock, mem_ctx);
+}
+
+const char *socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
+{
+       if (!sock->ops->get_my_addr) {
+               return NULL;
+       }
+
+       return sock->ops->get_my_addr(sock, mem_ctx);
+}
+
+int socket_get_my_port(struct socket_context *sock, TALLOC_CTX *mem_ctx)
+{
+       if (!sock->ops->get_my_port) {
+               return -1;
+       }
+
+       return sock->ops->get_my_port(sock, mem_ctx);
+}
+
+int socket_get_fd(struct socket_context *sock, TALLOC_CTX *mem_ctx)
+{
+       if (!sock->ops->get_fd) {
+               return -1;
+       }
+
+       return sock->ops->get_fd(sock, mem_ctx);
+}
+
+const struct socket_ops *socket_getops_byname(const char *name, enum socket_type type)
+{
+       if (strequal("ip", name) || strequal("ipv4", name)) {
+               return socket_ipv4_ops();
+       }
+
+       return NULL;
+}
diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h
new file mode 100644 (file)
index 0000000..dfc964b
--- /dev/null
@@ -0,0 +1,93 @@
+/* 
+   Unix SMB/CIFS implementation.
+   Socket functions
+   Copyright (C) Stefan Metzmacher 2004
+   
+   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 2 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, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _SAMBA_SOCKET_H
+#define _SAMBA_SOCKET_H
+
+struct socket_context;
+
+enum socket_type {
+       SOCKET_TYPE_STREAM
+};
+
+struct socket_ops {
+       const char *name;
+       enum socket_type type;
+
+       NTSTATUS (*init)(struct socket_context *sock);
+
+       /* client ops */
+       NTSTATUS (*connect)(struct socket_context *sock,
+                               const char *my_address, int my_port,
+                               const char *server_address, int server_port,
+                               uint32_t flags);
+
+       /* server ops */
+       NTSTATUS (*listen)(struct socket_context *sock,
+                               const char *my_address, int port, int queue_size, uint32_t flags);
+       NTSTATUS (*accept)(struct socket_context *sock,
+                               struct socket_context **new_sock, uint32_t flags);
+
+       /* general ops */
+       NTSTATUS (*recv)(struct socket_context *sock, TALLOC_CTX *mem_ctx, 
+                               DATA_BLOB *blob, size_t wantlen, uint32_t flags);
+       NTSTATUS (*send)(struct socket_context *sock, TALLOC_CTX *mem_ctx,
+                               const DATA_BLOB *blob, size_t *sendlen, uint32_t flags);
+
+       void (*close)(struct socket_context *sock);
+
+       NTSTATUS (*set_option)(struct socket_context *sock, const char *option, const char *val);
+
+       const char *(*get_peer_addr)(struct socket_context *sock, TALLOC_CTX *mem_ctx);
+       int (*get_peer_port)(struct socket_context *sock, TALLOC_CTX *mem_ctx);
+       const char *(*get_my_addr)(struct socket_context *sock, TALLOC_CTX *mem_ctx);
+       int (*get_my_port)(struct socket_context *sock, TALLOC_CTX *mem_ctx);
+
+       int (*get_fd)(struct socket_context *sock, TALLOC_CTX *mem_ctx);
+};
+
+enum socket_state {
+       SOCKET_STATE_UNDEFINED,
+
+       SOCKET_STATE_CLIENT_START,
+       SOCKET_STATE_CLIENT_CONNECTED,
+       SOCKET_STATE_CLIENT_STARTTLS,
+       SOCKET_STATE_CLIENT_ERROR,
+       
+       SOCKET_STATE_SERVER_LISTEN,
+       SOCKET_STATE_SERVER_CONNECTED,
+       SOCKET_STATE_SERVER_STARTTLS,
+       SOCKET_STATE_SERVER_ERROR
+};
+
+#define SOCKET_OPTION_BLOCK 0x00000001
+
+struct socket_context {
+       enum socket_type type;
+       enum socket_state state;
+       uint32_t flags;
+
+       int fd;
+
+       void *private_data;
+       const struct socket_ops *ops;
+};
+
+#endif /* _SAMBA_SOCKET_H */
diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c
new file mode 100644 (file)
index 0000000..90f289a
--- /dev/null
@@ -0,0 +1,293 @@
+/* 
+   Unix SMB/CIFS implementation.
+   Socket IPv4 functions
+   Copyright (C) Stefan Metzmacher 2004
+   
+   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 2 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, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+static NTSTATUS ipv4_tcp_init(struct socket_context *sock)
+{
+       sock->fd = socket(PF_INET, SOCK_STREAM, 0);
+       if (sock->fd == -1) {
+               /* TODO: we need to map from errno to NTSTATUS here! */ 
+               return NT_STATUS_FOOBAR;
+       }
+
+       return NT_STATUS_OK;
+}
+
+static void ipv4_tcp_close(struct socket_context *sock)
+{
+       close(sock->fd);
+}
+
+static NTSTATUS ipv4_tcp_connect(struct socket_context *sock,
+                                       const char *my_address, int my_port,
+                                       const char *srv_address, int srv_port,
+                                       uint32_t flags)
+{
+       struct sockaddr_in my_addr;
+       struct sockaddr_in srv_addr;
+       struct in_addr my_ip;
+       struct in_addr srv_ip;
+       int ret;
+
+       ret = inet_aton(my_address, &my_ip);
+       if (ret == 0) {
+               /* not a valid ipv4 address */
+               return NT_STATUS_FOOBAR;
+       }
+
+       ZERO_STRUCT(my_addr);
+#ifdef HAVE_SOCK_SIN_LEN
+       my_addr.sin_len         = sizeof(my_addr);
+#endif
+       my_addr.sin_addr        = my_ip;
+       my_addr.sin_port        = htons(my_port);
+       my_addr.sin_family      = PF_INET;
+
+       ret = inet_aton(srv_address, &srv_ip);
+       if (ret == 0) {
+               /* not a valid ipv4 address */
+               return NT_STATUS_FOOBAR;
+       }
+
+       ret = bind(sock->fd, &my_addr, sizeof(my_addr));
+       if (ret == -1) {
+               /* TODO: we need to map from errno to NTSTATUS here! */
+               return NT_STATUS_FOOBAR;
+       }
+
+       ZERO_STRUCT(srv_addr);
+#ifdef HAVE_SOCK_SIN_LEN
+       srv_addr.sin_len        = sizeof(srv_addr);
+#endif
+       srv_addr.sin_addr       = srv_ip;
+       srv_addr.sin_port       = htons(srv_port);
+       srv_addr.sin_family     = PF_INET;
+
+       if (!(flags & SOCKET_OPTION_BLOCK)) {
+               ret = set_blocking(sock->fd, False);
+               if (ret == -1) {
+                       /* TODO: we need to map from errno to NTSTATUS here! */
+                       return NT_STATUS_FOOBAR;
+               }
+       }
+
+
+       ret = connect(sock->fd, &srv_addr, sizeof(srv_addr));
+       if (ret == -1) {
+               /* TODO: we need to map from errno to NTSTATUS here! */
+               return NT_STATUS_FOOBAR;
+       }
+
+       sock->state = SOCKET_STATE_CLIENT_CONNECTED;
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS ipv4_tcp_listen(struct socket_context *sock,
+                                       const char *my_address, int port,
+                                       int queue_size, uint32_t flags)
+{
+       struct sockaddr_in my_addr;
+       struct in_addr ip_addr;
+       int ret;
+
+       ZERO_STRUCT(my_addr);
+
+       ret = inet_aton(my_address, &ip_addr);
+       if (ret == 0) {
+               /* not a valid ipv4 address */
+               return NT_STATUS_FOOBAR;
+       }
+
+#ifdef HAVE_SOCK_SIN_LEN
+       my_addr.sin_len         = sizeof(my_addr);
+#endif
+       my_addr.sin_addr        = ip_addr;
+       my_addr.sin_port        = htons(port);
+       my_addr.sin_family      = PF_INET;
+
+       ret = bind(sock->fd, &my_addr, sizeof(my_addr));
+       if (ret == -1) {
+               /* TODO: we need to map from errno to NTSTATUS here! */
+               return NT_STATUS_FOOBAR;
+       }
+
+       ret = listen(sock->fd, queue_size);
+       if (ret == -1) {
+               /* TODO: we need to map from errno to NTSTATUS here! */
+               return NT_STATUS_FOOBAR;
+       }
+
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_context **new_sock, uint32_t flags)
+{
+       struct sockaddr_in cli_addr;
+       socklen_t cli_addr_len = 0;
+       int new_fd;
+       int ret;
+
+       new_fd = accept(sock->fd, &cli_addr, &cli_addr_len);
+       if (new_fd == -1) {
+               /* TODO: we need to map from errno to NTSTATUS here! */
+               return NT_STATUS_FOOBAR;
+       }
+
+       if (!(flags & SOCKET_OPTION_BLOCK)) {
+               ret = set_blocking(sock->fd, False);
+               if (ret == -1) {
+                       /* TODO: we need to map from errno to NTSTATUS here! */
+                       return NT_STATUS_FOOBAR;
+               }
+       }
+
+       /* TODO: we could add a 'accept_check' hook here
+        *       which get the black/white lists via socket_set_accept_filter()
+        *       or something like that
+        *       --metze
+        */
+
+       (*new_sock) = talloc_p(NULL, struct socket_context);
+       if (!(*new_sock)) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* copy the socket_context */
+       (*new_sock)->type               = sock->type;
+       (*new_sock)->state              = SOCKET_STATE_SERVER_CONNECTED;
+       (*new_sock)->flags              = flags;
+
+       (*new_sock)->fd                 = new_fd;
+
+       (*new_sock)->private_data       = NULL;
+       (*new_sock)->ops                = sock->ops;
+
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx,
+                                       DATA_BLOB *blob, size_t wantlen, uint32_t flags)
+{
+       ssize_t gotlen;
+       void *buf;
+       int flgs = 0;
+
+       buf = talloc(mem_ctx, wantlen);
+       if (!buf) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* TODO: we need to map the flags here */
+
+       gotlen = recv(sock->fd, buf, wantlen, flgs);
+       if (gotlen == -1) {
+               talloc_free(buf);
+               /* TODO: we need to map from errno to NTSTATUS here! */
+               return NT_STATUS_FOOBAR;
+       }
+
+       blob->length = gotlen;
+       blob->data = buf;
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS ipv4_tcp_send(struct socket_context *sock, TALLOC_CTX *mem_ctx,
+                                       const DATA_BLOB *blob, size_t *sendlen, uint32_t flags)
+{
+       ssize_t len;
+       int flgs = 0;
+
+       /* TODO: we need to map the flags here */
+
+       len = send(sock->fd, blob->data, blob->length, flgs);
+       if (len == -1) {
+               /* TODO: we need to map from errno to NTSTATUS here! */
+               return NT_STATUS_FOOBAR;
+       }       
+
+       *sendlen = len;
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS ipv4_tcp_set_option(struct socket_context *sock, const char *option, const char *val)
+{
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
+static const char *ipv4_tcp_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
+{
+       return NULL;
+}
+
+static int ipv4_tcp_get_peer_port(struct socket_context *sock, TALLOC_CTX *mem_ctx)
+{
+       return -1;
+}
+
+static const char *ipv4_tcp_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
+{
+       return NULL;
+}
+
+static int ipv4_tcp_get_my_port(struct socket_context *sock, TALLOC_CTX *mem_ctx)
+{
+       return -1;
+}
+
+static int ipv4_tcp_get_fd(struct socket_context *sock, TALLOC_CTX *mem_ctx)
+{
+       return sock->fd;
+}
+
+static const struct socket_ops ipv4_tcp_ops = {
+       .name           = "ipv4",
+       .type           = SOCKET_TYPE_STREAM,
+
+       .init           = ipv4_tcp_init,
+       .connect        = ipv4_tcp_connect,
+       .listen         = ipv4_tcp_listen,
+       .accept         = ipv4_tcp_accept,
+       .recv           = ipv4_tcp_recv,
+       .send           = ipv4_tcp_send,
+       .close          = ipv4_tcp_close,
+
+       .set_option     = ipv4_tcp_set_option,
+
+       .get_peer_addr  = ipv4_tcp_get_peer_addr,
+       .get_peer_port  = ipv4_tcp_get_peer_port,
+       .get_my_addr    = ipv4_tcp_get_my_addr,
+       .get_my_port    = ipv4_tcp_get_my_port,
+
+       .get_fd         = ipv4_tcp_get_fd
+};
+
+const struct socket_ops *socket_ipv4_ops(void)
+{
+       return &ipv4_tcp_ops;
+}
+
+NTSTATUS socket_ipv4_init(void)
+{
+       return NT_STATUS_OK;
+}
index fe2a5b17ba3d96d5cc84b72111d6f2db7cd2a802..9293ea203833dd3ba6ab28b63052f42cf78b1836 100644 (file)
@@ -9,4 +9,4 @@ SMB_SUBSYSTEM(LIBSMB,[],
                libcli/climessage.o
                libcli/clideltree.o],
                [],
-               [LIBCLI LIBRPC])
+               [LIBCLI LIBRPC SOCKET])