summaryrefslogtreecommitdiff
path: root/source4/librpc/rpc/dcerpc_sock.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-10-27 03:15:42 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:04:49 -0500
commit9d055846f225bea4953822f40fab1d2f1a2e2d07 (patch)
tree9a513f3eeb7223a96e1df1d65060b095002e534e /source4/librpc/rpc/dcerpc_sock.c
parent5ae448116165a6bb9d792686db825b8b47f27201 (diff)
downloadsamba-9d055846f225bea4953822f40fab1d2f1a2e2d07.tar.gz
samba-9d055846f225bea4953822f40fab1d2f1a2e2d07.tar.bz2
samba-9d055846f225bea4953822f40fab1d2f1a2e2d07.zip
r3278: - rewrote the client side rpc connection code to use lib/socket/
rather than doing everything itself. This greatly simplifies the code, although I really don't like the socket_recv() interface (it always allocates memory for you, which means an extra memcpy in this code) - fixed several bugs in the socket_ipv4.c code, in particular client side code used a non-blocking connect but didn't handle EINPROGRESS, so it had no chance of working. Also fixed the error codes, using map_nt_error_from_unix() - cleaned up and expanded map_nt_error_from_unix() - changed interpret_addr2() to not take a mem_ctx. It makes absolutely no sense to allocate a fixed size 4 byte structure like this. Dozens of places in the code were also using interpret_addr2() incorrectly (precisely because the allocation made no sense) (This used to be commit 7f2c771b0e0e98c5c9e5cf662592d64d34ff1205)
Diffstat (limited to 'source4/librpc/rpc/dcerpc_sock.c')
-rw-r--r--source4/librpc/rpc/dcerpc_sock.c302
1 files changed, 78 insertions, 224 deletions
diff --git a/source4/librpc/rpc/dcerpc_sock.c b/source4/librpc/rpc/dcerpc_sock.c
index b22ada1d7f..fa2d565084 100644
--- a/source4/librpc/rpc/dcerpc_sock.c
+++ b/source4/librpc/rpc/dcerpc_sock.c
@@ -34,7 +34,7 @@ struct sock_blob {
struct sock_private {
struct event_context *event_ctx;
struct fd_event *fde;
- int fd;
+ struct socket_context *sock;
char *server_name;
uint32_t port;
@@ -55,9 +55,9 @@ static void sock_dead(struct dcerpc_pipe *p, NTSTATUS status)
{
struct sock_private *sock = p->transport.private;
- if (sock && sock->fd != -1) {
- close(sock->fd);
- sock->fd = -1;
+ if (sock && sock->sock != NULL) {
+ talloc_free(sock->sock);
+ sock->sock = NULL;
}
/* wipe any pending sends */
@@ -81,20 +81,19 @@ static void sock_process_send(struct dcerpc_pipe *p)
while (sock->pending_send) {
struct sock_blob *blob = sock->pending_send;
- ssize_t ret = write(sock->fd, blob->data.data, blob->data.length);
- if (ret == -1) {
- if (errno != EAGAIN && errno != EINTR) {
- sock_dead(p, NT_STATUS_NET_WRITE_FAULT);
- }
+ NTSTATUS status;
+ size_t sent;
+ status = socket_send(sock->sock, blob, &blob->data, &sent, 0);
+ if (NT_STATUS_IS_ERR(status)) {
+ sock_dead(p, NT_STATUS_NET_WRITE_FAULT);
break;
}
- if (ret == 0) {
- sock_dead(p, NT_STATUS_NET_WRITE_FAULT);
+ if (sent == 0) {
break;
}
- blob->data.data += ret;
- blob->data.length -= ret;
+ blob->data.data += sent;
+ blob->data.length -= sent;
if (blob->data.length != 0) {
break;
@@ -116,7 +115,8 @@ static void sock_process_send(struct dcerpc_pipe *p)
static void sock_process_recv(struct dcerpc_pipe *p)
{
struct sock_private *sock = p->transport.private;
- ssize_t ret;
+ NTSTATUS status;
+ DATA_BLOB blob;
if (sock->recv.data.data == NULL) {
sock->recv.data = data_blob_talloc(sock, NULL, MIN_HDR_SIZE);
@@ -126,20 +126,19 @@ static void sock_process_recv(struct dcerpc_pipe *p)
if (sock->recv.received < MIN_HDR_SIZE) {
uint32_t frag_length;
- ret = read(sock->fd, sock->recv.data.data,
- MIN_HDR_SIZE - sock->recv.received);
- if (ret == -1) {
- if (errno != EAGAIN && errno != EINTR) {
- sock_dead(p, NT_STATUS_NET_WRITE_FAULT);
- }
+ status = socket_recv(sock->sock, sock, &blob, MIN_HDR_SIZE - sock->recv.received, 0);
+ if (NT_STATUS_IS_ERR(status)) {
+ sock_dead(p, NT_STATUS_NET_WRITE_FAULT);
return;
}
- if (ret == 0) {
- sock_dead(p, NT_STATUS_NET_WRITE_FAULT);
+ if (blob.length == 0) {
return;
}
-
- sock->recv.received += ret;
+
+ memcpy(sock->recv.data.data + sock->recv.received,
+ blob.data, blob.length);
+ sock->recv.received += blob.length;
+ talloc_free(blob.data);
if (sock->recv.received != MIN_HDR_SIZE) {
return;
@@ -156,20 +155,18 @@ static void sock_process_recv(struct dcerpc_pipe *p)
}
/* read in the rest of the packet */
- ret = read(sock->fd, sock->recv.data.data + sock->recv.received,
- sock->recv.data.length - sock->recv.received);
- if (ret == -1) {
- if (errno != EAGAIN && errno != EINTR) {
- sock_dead(p, NT_STATUS_NET_WRITE_FAULT);
- }
+ status = socket_recv(sock->sock, sock, &blob, sock->recv.data.length - sock->recv.received, 0);
+ if (NT_STATUS_IS_ERR(status)) {
+ sock_dead(p, NT_STATUS_NET_WRITE_FAULT);
return;
}
- if (ret == 0) {
- sock_dead(p, NT_STATUS_NET_WRITE_FAULT);
+ if (blob.length == 0) {
return;
}
-
- sock->recv.received += ret;
+ memcpy(sock->recv.data.data + sock->recv.received,
+ blob.data, blob.length);
+ sock->recv.received += blob.length;
+ talloc_free(blob.data);
if (sock->recv.received != sock->recv.data.length) {
return;
@@ -199,7 +196,7 @@ static void sock_io_handler(struct event_context *ev, struct fd_event *fde,
sock_process_send(p);
}
- if (sock->fd == -1) {
+ if (sock->sock == NULL) {
return;
}
@@ -282,67 +279,50 @@ static const char *sock_peer_name(struct dcerpc_pipe *p)
}
/*
- open a rpc connection to a named pipe
+ open a rpc connection using the generic socket library
*/
-NTSTATUS dcerpc_pipe_open_tcp(struct dcerpc_pipe **p,
- const char *server,
- uint32_t port,
- int family)
+static NTSTATUS dcerpc_pipe_open_socket(struct dcerpc_pipe **p,
+ const char *server,
+ uint32_t port,
+ const char *type,
+ enum dcerpc_transport_t transport)
{
struct sock_private *sock;
- int fd, gai_err;
+ struct socket_context *socket_ctx;
struct fd_event fde;
- struct addrinfo hints, *res, *tmpres;
- char portname[16];
+ NTSTATUS status;
if (port == 0) {
port = EPMAPPER_PORT;
}
- memset(&hints, 0, sizeof(struct addrinfo));
-
- hints.ai_family = family;
- hints.ai_socktype = SOCK_STREAM;
-
- snprintf(portname, sizeof(portname)-1, "%d", port);
-
- gai_err = getaddrinfo(server, portname, &hints, &res);
- if (gai_err < 0)
- {
- DEBUG(0, ("Unable to connect to %s:%d : %s\n", server, port, gai_strerror(gai_err)));
- return NT_STATUS_BAD_NETWORK_NAME;
+ if (!(*p = dcerpc_pipe_init())) {
+ return NT_STATUS_NO_MEMORY;
}
-
- tmpres = res;
-
- while (tmpres) {
- fd = socket(tmpres->ai_family, tmpres->ai_socktype, tmpres->ai_protocol);
-
- if(fd >= 0) {
- if (connect(fd, tmpres->ai_addr, tmpres->ai_addrlen) == 0)
- break;
- fd = -1;
- }
-
- tmpres = tmpres->ai_next;
+
+ sock = talloc_p((*p), struct sock_private);
+ if (!sock) {
+ talloc_free(*p);
+ return NT_STATUS_NO_MEMORY;
}
- freeaddrinfo(res);
-
- if (fd == -1) {
- return NT_STATUS_PORT_CONNECTION_REFUSED;
+ status = socket_create(type, SOCKET_TYPE_STREAM, &socket_ctx, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(*p);
+ return status;
}
+ talloc_steal(sock, socket_ctx);
- set_socket_options(fd, lp_socket_options());
-
- if (!(*p = dcerpc_pipe_init())) {
- return NT_STATUS_NO_MEMORY;
+ status = socket_connect(socket_ctx, NULL, 0, server, port, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(*p);
+ return status;
}
-
+
/*
fill in the transport methods
*/
- (*p)->transport.transport = NCACN_IP_TCP;
+ (*p)->transport.transport = transport;
(*p)->transport.private = NULL;
(*p)->transport.send_request = sock_send_request;
@@ -353,13 +333,7 @@ NTSTATUS dcerpc_pipe_open_tcp(struct dcerpc_pipe **p,
(*p)->transport.shutdown_pipe = sock_shutdown_pipe;
(*p)->transport.peer_name = sock_peer_name;
- sock = talloc((*p), sizeof(*sock));
- if (!sock) {
- dcerpc_pipe_close(*p);
- return NT_STATUS_NO_MEMORY;
- }
-
- sock->fd = fd;
+ sock->sock = socket_ctx;
sock->server_name = talloc_strdup((*p), server);
sock->event_ctx = event_context_init(sock);
sock->pending_send = NULL;
@@ -367,7 +341,7 @@ NTSTATUS dcerpc_pipe_open_tcp(struct dcerpc_pipe **p,
sock->recv.data = data_blob(NULL, 0);
sock->recv.pending_count = 0;
- fde.fd = fd;
+ fde.fd = socket_get_fd(sock->sock);
fde.flags = 0;
fde.handler = sock_io_handler;
fde.private = *p;
@@ -379,160 +353,40 @@ NTSTATUS dcerpc_pipe_open_tcp(struct dcerpc_pipe **p,
/* ensure we don't get SIGPIPE */
BlockSignals(True,SIGPIPE);
- return NT_STATUS_OK;
+ return NT_STATUS_OK;
}
/*
- open a rpc connection to a unix socket
+ open a rpc connection using tcp
*/
-NTSTATUS dcerpc_pipe_open_unix_stream(struct dcerpc_pipe **p,
- const char *path)
+NTSTATUS dcerpc_pipe_open_tcp(struct dcerpc_pipe **p, const char *server, uint32_t port)
{
- struct sock_private *sock;
- int fd;
- struct fd_event fde;
- struct sockaddr_un sa;
-
- fd = socket(PF_UNIX, SOCK_STREAM, 0);
-
- if (fd < 0) {
- return NT_STATUS_NOT_SUPPORTED;
- }
-
- sa.sun_family = AF_UNIX;
- strncpy(sa.sun_path, path, sizeof(sa.sun_path));
-
- if (connect(fd, &sa, sizeof(sa)) < 0) {
- DEBUG(0, ("Unable to connect to unix socket %s: %s\n", path, strerror(errno)));
- return NT_STATUS_BAD_NETWORK_NAME;
- }
-
- set_socket_options(fd, lp_socket_options());
-
- if (!(*p = dcerpc_pipe_init())) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /*
- fill in the transport methods
- */
- (*p)->transport.transport = NCACN_UNIX_STREAM;
- (*p)->transport.private = NULL;
-
- (*p)->transport.send_request = sock_send_request;
- (*p)->transport.send_read = sock_send_read;
- (*p)->transport.event_context = sock_event_context;
- (*p)->transport.recv_data = NULL;
-
- (*p)->transport.shutdown_pipe = sock_shutdown_pipe;
- (*p)->transport.peer_name = sock_peer_name;
-
- sock = talloc((*p), sizeof(*sock));
- if (!sock) {
- dcerpc_pipe_close(*p);
- return NT_STATUS_NO_MEMORY;
- }
-
- sock->fd = fd;
- sock->server_name = talloc_strdup((*p), path);
- sock->event_ctx = event_context_init(sock);
- sock->pending_send = NULL;
- sock->recv.received = 0;
- sock->recv.data = data_blob(NULL, 0);
- sock->recv.pending_count = 0;
-
- fde.fd = fd;
- fde.flags = 0;
- fde.handler = sock_io_handler;
- fde.private = *p;
-
- sock->fde = event_add_fd(sock->event_ctx, &fde);
-
- (*p)->transport.private = sock;
-
- /* ensure we don't get SIGPIPE */
- BlockSignals(True,SIGPIPE);
+ return dcerpc_pipe_open_socket(p, server, port, "ip", NCACN_IP_TCP);
+}
- return NT_STATUS_OK;
+/*
+ open a rpc connection to a unix socket
+*/
+NTSTATUS dcerpc_pipe_open_unix_stream(struct dcerpc_pipe **p, const char *path)
+{
+ return dcerpc_pipe_open_socket(p, path, 0, "unix", NCACN_UNIX_STREAM);
}
/*
open a rpc connection to a named pipe
*/
-NTSTATUS dcerpc_pipe_open_pipe(struct dcerpc_pipe **p,
- const char *identifier)
+NTSTATUS dcerpc_pipe_open_pipe(struct dcerpc_pipe **p, const char *identifier)
{
- struct sock_private *sock;
- int fd;
- struct fd_event fde;
- struct sockaddr_un sa;
+ NTSTATUS status;
char *canon, *full_path;
- if (!(*p = dcerpc_pipe_init())) {
- return NT_STATUS_NO_MEMORY;
- }
-
- canon = talloc_strdup(*p, identifier);
+ canon = talloc_strdup(NULL, identifier);
string_replace(canon, '/', '\\');
+ full_path = talloc_asprintf(canon, "%s/%s", lp_ncalrpc_dir(), canon);
- full_path = talloc_asprintf(*p, "%s/%s", lp_ncalrpc_dir(), canon);
-
- fd = socket(PF_UNIX, SOCK_STREAM, 0);
-
- if (fd < 0) {
- return NT_STATUS_NOT_SUPPORTED;
- }
-
- sa.sun_family = AF_UNIX;
- strncpy(sa.sun_path, full_path, sizeof(sa.sun_path));
-
- if (connect(fd, &sa, sizeof(sa)) < 0) {
- DEBUG(0, ("Unable to connect to unix socket %s (%s): %s\n", full_path, identifier, strerror(errno)));
- return NT_STATUS_BAD_NETWORK_NAME;
- }
-
- set_socket_options(fd, lp_socket_options());
-
- /*
- fill in the transport methods
- */
- (*p)->transport.transport = NCALRPC;
- (*p)->transport.private = NULL;
-
- (*p)->transport.send_request = sock_send_request;
- (*p)->transport.send_read = sock_send_read;
- (*p)->transport.event_context = sock_event_context;
- (*p)->transport.recv_data = NULL;
-
- (*p)->transport.shutdown_pipe = sock_shutdown_pipe;
- (*p)->transport.peer_name = sock_peer_name;
-
- sock = talloc((*p), sizeof(*sock));
- if (!sock) {
- dcerpc_pipe_close(*p);
- return NT_STATUS_NO_MEMORY;
- }
-
- sock->fd = fd;
- sock->server_name = full_path;
- sock->event_ctx = event_context_init(sock);
- sock->pending_send = NULL;
- sock->recv.received = 0;
- sock->recv.data = data_blob(NULL, 0);
- sock->recv.pending_count = 0;
-
- fde.fd = fd;
- fde.flags = 0;
- fde.handler = sock_io_handler;
- fde.private = *p;
-
- sock->fde = event_add_fd(sock->event_ctx, &fde);
-
- (*p)->transport.private = sock;
-
- /* ensure we don't get SIGPIPE */
- BlockSignals(True,SIGPIPE);
+ status = dcerpc_pipe_open_socket(p, full_path, 0, "unix", NCALRPC);
+ talloc_free(canon);
- return NT_STATUS_OK;
+ return status;
}