From 32a3aa932d2556baf7ee7d38bf694484bf9b04cb Mon Sep 17 00:00:00 2001 From: Rafal Szczesniak Date: Sun, 19 Feb 2006 16:58:48 +0000 Subject: r13561: Turn all dcerpc connect and socket functions to async version. Now, each rpc interface (named pipe, tcp/ip, lrpc and unix socket) works asynchronously. Comments to follow. rafal (This used to be commit 789f9d43db7ea59e79d5aa498e2e9fd077448825) --- source4/librpc/rpc/dcerpc_connect.c | 243 +++++++++++++++++++++++++++++ source4/librpc/rpc/dcerpc_sock.c | 302 ++++++++++++++++++++++++++++++++---- source4/librpc/rpc/dcerpc_util.c | 81 +--------- 3 files changed, 517 insertions(+), 109 deletions(-) (limited to 'source4/librpc') diff --git a/source4/librpc/rpc/dcerpc_connect.c b/source4/librpc/rpc/dcerpc_connect.c index 67dfda6d7a..fa02bca697 100644 --- a/source4/librpc/rpc/dcerpc_connect.c +++ b/source4/librpc/rpc/dcerpc_connect.c @@ -324,3 +324,246 @@ NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2(TALLOC_CTX *mem_ctx, c = dcerpc_pipe_connect_ncacn_np_smb2_send(mem_ctx, io); return dcerpc_pipe_connect_ncacn_np_smb2_recv(c); } + + +struct pipe_ip_tcp_state { + struct dcerpc_pipe_connect io; + const char *host; + uint32_t port; +}; + + +void continue_pipe_open_ncacn_ip_tcp(struct composite_context *ctx) +{ + struct composite_context *c = talloc_get_type(ctx->async.private_data, + struct composite_context); + struct pipe_ip_tcp_state *s = talloc_get_type(c->private_data, + struct pipe_ip_tcp_state); + + c->status = dcerpc_pipe_open_tcp_recv(ctx); + if (!NT_STATUS_IS_OK(c->status)) { + DEBUG(0,("Failed to connect to %s:%d - %s\n", s->host, s->port, + nt_errstr(c->status))); + composite_error(c, c->status); + return; + } + + composite_done(c); +} + + +struct composite_context* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CTX *mem_ctx, + struct dcerpc_pipe_connect *io) +{ + struct composite_context *c; + struct pipe_ip_tcp_state *s; + struct composite_context *pipe_req; + + /* composite context allocation and setup */ + c = talloc_zero(mem_ctx, struct composite_context); + if (c == NULL) return NULL; + + s = talloc_zero(c, struct pipe_ip_tcp_state); + if (s == NULL) { + composite_error(c, NT_STATUS_NO_MEMORY); + goto done; + } + + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->private_data = s; + c->event_ctx = io->pipe->conn->event_ctx; + + s->io = *io; + s->host = talloc_strdup(c, io->binding->host); + s->port = atoi(io->binding->endpoint); /* port number is a binding endpoint here */ + + pipe_req = dcerpc_pipe_open_tcp_send(s->io.pipe->conn, s->host, s->port); + if (pipe_req == NULL) { + composite_error(c, NT_STATUS_NO_MEMORY); + goto done; + } + + composite_continue(c, pipe_req, continue_pipe_open_ncacn_ip_tcp, c); +done: + return c; +} + + +NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp_recv(struct composite_context *c) +{ + NTSTATUS status = composite_wait(c); + + talloc_free(c); + return status; +} + + +NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(TALLOC_CTX *mem_ctx, + struct dcerpc_pipe_connect *io) +{ + struct composite_context *c; + c = dcerpc_pipe_connect_ncacn_ip_tcp_send(mem_ctx, io); + return dcerpc_pipe_connect_ncacn_ip_tcp_recv(c); +} + + +struct pipe_unix_state { + struct dcerpc_pipe_connect io; + const char *path; +}; + + +void continue_pipe_open_ncacn_unix_stream(struct composite_context *ctx) +{ + struct composite_context *c = talloc_get_type(ctx->async.private_data, + struct composite_context); + struct pipe_unix_state *s = talloc_get_type(c->private_data, + struct pipe_unix_state); + + c->status = dcerpc_pipe_open_unix_stream_recv(ctx); + if (!NT_STATUS_IS_OK(c->status)) { + DEBUG(0,("Failed to open unix socket %s - %s\n", + s->io.binding->endpoint, nt_errstr(c->status))); + composite_error(c, c->status); + return; + } + + composite_done(c); +} + + +struct composite_context* dcerpc_pipe_connect_ncacn_unix_stream_send(TALLOC_CTX *mem_ctx, + struct dcerpc_pipe_connect *io) +{ + struct composite_context *c; + struct pipe_unix_state *s; + struct composite_context *pipe_req; + + /* composite context allocation and setup */ + c = talloc_zero(mem_ctx, struct composite_context); + if (c == NULL) return NULL; + + s = talloc_zero(c, struct pipe_unix_state); + if (s == NULL) { + composite_error(c, NT_STATUS_NO_MEMORY); + goto done; + } + + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->private_data = s; + c->event_ctx = io->pipe->conn->event_ctx; + + s->io = *io; + + if (!io->binding->endpoint) { + DEBUG(0, ("Path to unix socket not specified\n")); + composite_error(c, NT_STATUS_INVALID_PARAMETER); + goto done; + } + + s->path = talloc_strdup(c, io->binding->endpoint); /* path is a binding endpoint here */ + + pipe_req = dcerpc_pipe_open_unix_stream_send(s->io.pipe->conn, s->path); + if (pipe_req == NULL) { + composite_error(c, NT_STATUS_NO_MEMORY); + goto done; + } + + composite_continue(c, pipe_req, continue_pipe_open_ncacn_unix_stream, c); +done: + return c; +} + + +NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream_recv(struct composite_context *c) +{ + NTSTATUS status = composite_wait(c); + + talloc_free(c); + return status; +} + + +NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream(TALLOC_CTX *mem_ctx, + struct dcerpc_pipe_connect *io) +{ + struct composite_context *c; + c = dcerpc_pipe_connect_ncacn_unix_stream_send(mem_ctx, io); + return dcerpc_pipe_connect_ncacn_unix_stream_recv(c); +} + + +struct pipe_ncalrpc_state { + struct dcerpc_pipe_connect io; +}; + + +void continue_pipe_open_ncalrpc(struct composite_context *ctx) +{ + struct composite_context *c = talloc_get_type(ctx->async.private_data, + struct composite_context); + struct pipe_ncalrpc_state *s = talloc_get_type(c->private_data, + struct pipe_ncalrpc_state); + + c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx); + if (!NT_STATUS_IS_OK(c->status)) { + DEBUG(0,("Failed to open ncalrpc pipe '%s' - %s\n", s->io.binding->endpoint, + nt_errstr(c->status))); + composite_error(c, c->status); + return; + } + + composite_done(c); +} + + +struct composite_context* dcerpc_pipe_connect_ncalrpc_send(TALLOC_CTX *mem_ctx, + struct dcerpc_pipe_connect *io) +{ + struct composite_context *c; + struct pipe_ncalrpc_state *s; + struct composite_context *pipe_req; + + /* composite context allocation and setup */ + c = talloc_zero(mem_ctx, struct composite_context); + if (c == NULL) return NULL; + + s = talloc_zero(c, struct pipe_ncalrpc_state); + if (s == NULL) { + composite_error(c, NT_STATUS_NO_MEMORY); + goto done; + } + + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->private_data = s; + c->event_ctx = io->pipe->conn->event_ctx; + + s->io = *io; + + pipe_req = dcerpc_pipe_open_pipe_send(s->io.pipe->conn, s->io.binding->endpoint); + if (pipe_req == NULL) { + composite_error(c, NT_STATUS_NO_MEMORY); + goto done; + } + + composite_continue(c, pipe_req, continue_pipe_open_ncalrpc, c); +done: + return c; +} + + +NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c) +{ + NTSTATUS status = composite_wait(c); + + talloc_free(c); + return status; +} + + +NTSTATUS dcerpc_pipe_connect_ncalrpc(TALLOC_CTX *mem_ctx, + struct dcerpc_pipe_connect *io) +{ + struct composite_context *c = dcerpc_pipe_connect_ncalrpc_send(mem_ctx, io); + return dcerpc_pipe_connect_ncalrpc_recv(c); +} diff --git a/source4/librpc/rpc/dcerpc_sock.c b/source4/librpc/rpc/dcerpc_sock.c index 75684aaf8a..fecbe22548 100644 --- a/source4/librpc/rpc/dcerpc_sock.c +++ b/source4/librpc/rpc/dcerpc_sock.c @@ -348,70 +348,304 @@ NTSTATUS dcerpc_pipe_open_socket(struct dcerpc_connection *conn, } -/* - open a rpc connection using tcp -*/ -NTSTATUS dcerpc_pipe_open_tcp(struct dcerpc_connection *c, const char *server, uint32_t port) -{ - NTSTATUS status; +struct pipe_tcp_state { + const char *server; + uint32_t port; struct socket_address *srvaddr; + struct dcerpc_connection *conn; +}; - srvaddr = socket_address_from_strings(c, "ipv6", server, port); - if (!srvaddr) { - return NT_STATUS_NO_MEMORY; + +void continue_ipv6_open_socket(struct composite_context *ctx); +void continue_ipv4_open_socket(struct composite_context *ctx); + + +void continue_ipv6_open_socket(struct composite_context *ctx) +{ + struct composite_context *c = talloc_get_type(ctx->async.private_data, + struct composite_context); + struct pipe_tcp_state *s = talloc_get_type(c->private_data, + struct pipe_tcp_state); + struct composite_context *sock_ipv4_req; + + c->status = dcerpc_pipe_open_socket_recv(ctx); + if (NT_STATUS_IS_OK(c->status)) return; + + talloc_free(s->srvaddr); + + s->srvaddr = socket_address_from_strings(s->conn, "ipv4", s->server, s->port); + if (!s->srvaddr) { + composite_error(c, NT_STATUS_NO_MEMORY); + return; } - /* Try IPv6 first */ - status = dcerpc_pipe_open_socket(c, srvaddr, NCACN_IP_TCP); - if (NT_STATUS_IS_OK(status)) { - return status; + /* Try IPv4 if IPv6 fails */ + sock_ipv4_req = dcerpc_pipe_open_socket_send(c, s->conn, s->srvaddr, NCACN_IP_TCP); + if (sock_ipv4_req == NULL) { + composite_error(c, NT_STATUS_NO_MEMORY); + return; } - talloc_free(srvaddr); - srvaddr = socket_address_from_strings(c, "ipv4", server, port); - if (!srvaddr) { - return NT_STATUS_NO_MEMORY; + composite_continue(c, sock_ipv4_req, continue_ipv4_open_socket, c); +} + + +void continue_ipv4_open_socket(struct composite_context *ctx) +{ + struct composite_context *c = talloc_get_type(ctx->async.private_data, + struct composite_context); + struct pipe_tcp_state *s = talloc_get_type(c->private_data, + struct pipe_tcp_state); + + c->status = dcerpc_pipe_open_socket_recv(ctx); + if (NT_STATUS_IS_OK(c->status)) { + composite_done(c); + return; } + + DEBUG(0, ("Failed to connect host %s on port %d - %s.\n", + s->server, s->port, nt_errstr(c->status))); + + composite_error(c, c->status); +} + + +struct composite_context* dcerpc_pipe_open_tcp_send(struct dcerpc_connection *conn, + const char* server, uint32_t port) +{ + struct composite_context *c; + struct composite_context *sock_ipv6_req; + struct pipe_tcp_state *s; + + /* composite context allocation and setup */ + c = talloc_zero(conn, struct composite_context); + if (c == NULL) return NULL; + + s = talloc_zero(c, struct pipe_tcp_state); + if (s == NULL) { + composite_error(c, NT_STATUS_NO_MEMORY); + goto done; + } + + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->private_data = s; + c->event_ctx = conn->event_ctx; + + s->server = talloc_strdup(c, server); + s->port = port; + s->conn = conn; - return dcerpc_pipe_open_socket(c, srvaddr, NCACN_IP_TCP); + s->srvaddr = socket_address_from_strings(s->conn, "ipv6", s->server, s->port); + if (!s->srvaddr) { + composite_error(c, NT_STATUS_NO_MEMORY); + goto done; + } + + /* Try IPv6 first */ + sock_ipv6_req = dcerpc_pipe_open_socket_send(c, s->conn, s->srvaddr, NCACN_IP_TCP); + if (sock_ipv6_req == NULL) { + composite_error(c, NT_STATUS_NO_MEMORY); + goto done; + } + + composite_continue(c, sock_ipv6_req, continue_ipv6_open_socket, c); +done: + return c; } + +NTSTATUS dcerpc_pipe_open_tcp_recv(struct composite_context *c) +{ + NTSTATUS status; + status = composite_wait(c); + + talloc_free(c); + return status; +} + + /* - open a rpc connection to a unix socket + open a rpc connection using tcp - sync version */ -NTSTATUS dcerpc_pipe_open_unix_stream(struct dcerpc_connection *c, const char *path) +NTSTATUS dcerpc_pipe_open_tcp(struct dcerpc_connection *conn, const char *server, + uint32_t port) { + struct composite_context *c; + + c = dcerpc_pipe_open_tcp_send(conn, server, port); + return dcerpc_pipe_open_tcp_recv(c); +} + + +struct pipe_unix_state { + const char *path; struct socket_address *srvaddr; + struct dcerpc_connection *conn; +}; - srvaddr = socket_address_from_strings(c, "unix", path, 0); - if (!srvaddr) { - return NT_STATUS_NO_MEMORY; + +void continue_unix_open_socket(struct composite_context *ctx) +{ + struct composite_context *c = talloc_get_type(ctx->async.private_data, + struct composite_context); + + c->status = dcerpc_pipe_open_socket_recv(ctx); + if (NT_STATUS_IS_OK(c->status)) { + composite_done(c); + return; } - return dcerpc_pipe_open_socket(c, srvaddr, NCALRPC); + composite_error(c, c->status); } + +struct composite_context *dcerpc_pipe_open_unix_stream_send(struct dcerpc_connection *conn, + const char *path) +{ + struct composite_context *c; + struct composite_context *sock_unix_req; + struct pipe_unix_state *s; + + /* composite context allocation and setup */ + c = talloc_zero(conn, struct composite_context); + if (c == NULL) return NULL; + + s = talloc_zero(c, struct pipe_unix_state); + if (s == NULL) { + composite_error(c, NT_STATUS_NO_MEMORY); + goto done; + } + + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->private_data = s; + c->event_ctx = conn->event_ctx; + + s->path = talloc_strdup(c, path); + s->conn = conn; + + s->srvaddr = socket_address_from_strings(conn, "unix", s->path, 0); + if (s->srvaddr == NULL) { + composite_error(c, NT_STATUS_NO_MEMORY); + goto done; + } + + sock_unix_req = dcerpc_pipe_open_socket_send(c, s->conn, s->srvaddr, NCALRPC); + if (sock_unix_req == NULL) { + composite_error(c, NT_STATUS_NO_MEMORY); + goto done; + } + + composite_continue(c, sock_unix_req, continue_unix_open_socket, c); + +done: + return c; +} + + +NTSTATUS dcerpc_pipe_open_unix_stream_recv(struct composite_context *c) +{ + NTSTATUS status = composite_wait(c); + + talloc_free(c); + return status; +} + + /* - open a rpc connection to a named pipe + open a rpc connection to a unix socket - sync version */ -NTSTATUS dcerpc_pipe_open_pipe(struct dcerpc_connection *c, const char *identifier) +NTSTATUS dcerpc_pipe_open_unix_stream(struct dcerpc_connection *conn, const char *path) { - NTSTATUS status; - char *canon, *full_path; + struct composite_context *c = dcerpc_pipe_open_unix_stream_send(conn, path); + return dcerpc_pipe_open_unix_stream_recv(c); +} + + +struct pipe_np_state { + char *full_path; struct socket_address *srvaddr; + struct dcerpc_connection *conn; +}; + + +void continue_np_open_socket(struct composite_context *ctx) +{ + struct composite_context *c = talloc_get_type(ctx->async.private_data, + struct composite_context); + + c->status = dcerpc_pipe_open_socket_recv(ctx); + if (NT_STATUS_IS_OK(c->status)) { + composite_done(c); + return; + } + + composite_error(c, c->status); +} + + +struct composite_context* dcerpc_pipe_open_pipe_send(struct dcerpc_connection *conn, + const char *identifier) +{ + char *canon; + + struct composite_context *c; + struct composite_context *sock_np_req; + struct pipe_np_state *s; - canon = talloc_strdup(NULL, identifier); + /* composite context allocation and setup */ + c = talloc_zero(conn, struct composite_context); + if (c == NULL) return NULL; + + s = talloc_zero(c, struct pipe_np_state); + if (s == NULL) { + composite_error(c, NT_STATUS_NO_MEMORY); + goto done; + } + + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->private_data = s; + c->event_ctx = conn->event_ctx; + + canon = talloc_strdup(c, identifier); + s->conn = conn; string_replace(canon, '/', '\\'); - full_path = talloc_asprintf(canon, "%s/%s", lp_ncalrpc_dir(), canon); + s->full_path = talloc_asprintf(canon, "%s/%s", lp_ncalrpc_dir(), canon); - srvaddr = socket_address_from_strings(c, "unix", full_path, 0); - if (!srvaddr) { - return NT_STATUS_NO_MEMORY; + s->srvaddr = socket_address_from_strings(conn, "unix", s->full_path, 0); + if (s->srvaddr == NULL) { + composite_error(c, NT_STATUS_NO_MEMORY); + goto done; + } + + sock_np_req = dcerpc_pipe_open_socket_send(c, s->conn, s->srvaddr, NCALRPC); + if (sock_np_req == NULL) { + composite_error(c, NT_STATUS_NO_MEMORY); + goto done; } - status = dcerpc_pipe_open_socket(c, srvaddr, NCALRPC); + composite_continue(c, sock_np_req, continue_np_open_socket, c); + +done: talloc_free(canon); + return c; +} + +NTSTATUS dcerpc_pipe_open_pipe_recv(struct composite_context *c) +{ + NTSTATUS status = composite_wait(c); + + talloc_free(c); return status; } + + +/* + open a rpc connection to a named pipe - sync version +*/ +NTSTATUS dcerpc_pipe_open_pipe(struct dcerpc_connection *conn, const char *identifier) +{ + struct composite_context *c = dcerpc_pipe_open_pipe_send(conn, identifier); + return dcerpc_pipe_open_pipe_recv(c); +} diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index 6ef91b87b0..011ed9d81e 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -956,75 +956,6 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(TALLOC_CTX *tmp_ctx, } -/* open a rpc connection to a rpc pipe on SMP using the binding - structure to determine the endpoint and options */ -static NTSTATUS dcerpc_pipe_connect_ncalrpc(TALLOC_CTX *tmp_ctx, - struct dcerpc_pipe *p, - struct dcerpc_binding *binding, - const struct dcerpc_interface_table *table) -{ - NTSTATUS status; - - status = dcerpc_pipe_open_pipe(p->conn, binding->endpoint); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("Failed to open ncalrpc pipe '%s' - %s\n", - binding->endpoint, nt_errstr(status))); - return status; - } - - return status; -} - - - -/* open a rpc connection to a rpc pipe on SMP using the binding - structure to determine the endpoint and options */ -static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream(TALLOC_CTX *tmp_ctx, - struct dcerpc_pipe *p, - struct dcerpc_binding *binding, - const struct dcerpc_interface_table *table) -{ - NTSTATUS status; - - if (!binding->endpoint) { - DEBUG(0, ("Path to unix socket not specified\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - status = dcerpc_pipe_open_unix_stream(p->conn, binding->endpoint); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("Failed to open unix socket %s - %s\n", - binding->endpoint, nt_errstr(status))); - talloc_free(p); - return status; - } - - return status; -} - -/* open a rpc connection to a rpc pipe on TCP/IP sockets using the binding - structure to determine the endpoint and options */ -static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(TALLOC_CTX *tmp_ctx, - struct dcerpc_pipe *p, - struct dcerpc_binding *binding, - const struct dcerpc_interface_table *table) -{ - NTSTATUS status; - uint32_t port = 0; - - port = atoi(binding->endpoint); - - status = dcerpc_pipe_open_tcp(p->conn, binding->host, port); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("Failed to connect to %s:%d - %s\n", - binding->host, port, nt_errstr(status))); - return status; - } - - return status; -} - - /* open a rpc connection to a rpc pipe, using the specified binding structure to determine the endpoint and options */ NTSTATUS dcerpc_pipe_connect_b(TALLOC_CTX *parent_ctx, @@ -1082,17 +1013,17 @@ NTSTATUS dcerpc_pipe_connect_b(TALLOC_CTX *parent_ctx, break; case NCACN_IP_TCP: - status = dcerpc_pipe_connect_ncacn_ip_tcp(tmp_ctx, - p, binding, table); + status = dcerpc_pipe_connect_ncacn_ip_tcp(tmp_ctx, &pc); break; + case NCACN_UNIX_STREAM: - status = dcerpc_pipe_connect_ncacn_unix_stream(tmp_ctx, - p, binding, table); + status = dcerpc_pipe_connect_ncacn_unix_stream(tmp_ctx, &pc); break; + case NCALRPC: - status = dcerpc_pipe_connect_ncalrpc(tmp_ctx, - p, binding, table); + status = dcerpc_pipe_connect_ncalrpc(tmp_ctx, &pc); break; + default: return NT_STATUS_NOT_SUPPORTED; } -- cgit