diff options
author | Volker Lendecke <vlendec@samba.org> | 2005-10-28 11:02:42 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:45:27 -0500 |
commit | 134b2488c82ae13392121f71e4960178a38f3e01 (patch) | |
tree | f002f6d68b66654d18f53a46df5459fbfd241b1e | |
parent | 3dc75cc84f92af9a72d52e7c9299b47c01368544 (diff) | |
download | samba-134b2488c82ae13392121f71e4960178a38f3e01.tar.gz samba-134b2488c82ae13392121f71e4960178a38f3e01.tar.xz samba-134b2488c82ae13392121f71e4960178a38f3e01.zip |
r11369: Implement socket_connect_multi: Connect to multiple ipv4 tcp ports in
sequence, with a 2-millisecond timeout between firing the syn packets. Build
smbcli_sock_connect_send upon that.
Volker
(This used to be commit 5718df44d90d113304c5deed1e2e7f82ff9e928f)
-rw-r--r-- | source4/include/structs.h | 1 | ||||
-rw-r--r-- | source4/lib/socket/config.mk | 1 | ||||
-rw-r--r-- | source4/lib/socket/connect_multi.c | 266 | ||||
-rw-r--r-- | source4/lib/socket/socket.h | 15 | ||||
-rw-r--r-- | source4/libcli/cliconnect.c | 8 | ||||
-rw-r--r-- | source4/libcli/config.mk | 1 | ||||
-rw-r--r-- | source4/libcli/ldap/ldap_client.c | 17 | ||||
-rw-r--r-- | source4/libcli/raw/clisocket.c | 324 | ||||
-rw-r--r-- | source4/libcli/smb_composite/connect.c | 42 | ||||
-rw-r--r-- | source4/libcli/smb_composite/connect_multi.c | 188 |
10 files changed, 437 insertions, 426 deletions
diff --git a/source4/include/structs.h b/source4/include/structs.h index 950d0baaa21..b72fdf7f23e 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -330,5 +330,6 @@ struct param_section; struct param; struct socket_context; +struct smbcli_socket; struct _krb5_krb_auth_data; diff --git a/source4/lib/socket/config.mk b/source4/lib/socket/config.mk index aa40975e4e0..64b542b7bce 100644 --- a/source4/lib/socket/config.mk +++ b/source4/lib/socket/config.mk @@ -36,6 +36,7 @@ INIT_OBJ_FILES = \ socket.o ADD_OBJ_FILES = \ access.o \ + connect_multi.o \ connect.o NOPROTO=YES # End SUBSYSTEM SOCKET diff --git a/source4/lib/socket/connect_multi.c b/source4/lib/socket/connect_multi.c new file mode 100644 index 00000000000..2724601ad07 --- /dev/null +++ b/source4/lib/socket/connect_multi.c @@ -0,0 +1,266 @@ +/* + Unix SMB/CIFS implementation. + + Fire connect requests to a host and a number of ports, with a timeout + between the connect request. Return if the first connect comes back + successfully or return the last error. + + Copyright (C) Volker Lendecke 2005 + + 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" +#include "lib/socket/socket.h" +#include "lib/events/events.h" +#include "libcli/composite/composite.h" + + +struct connect_multi_state { + struct composite_context *ctx; + const char *server_address; + int num_ports; + uint16_t *ports; + + struct socket_context *result; + uint16_t result_port; + + int num_connects_sent, num_connects_in_fly; + struct fd_event **write_events; + struct socket_context **sockets; + struct timed_event *next_timeout; +}; + +static void connect_multi_connect_handler(struct event_context *ev, + struct fd_event *fde, + uint16_t flags, void *p); +static NTSTATUS connect_multi_next_socket(struct connect_multi_state *state); +static void connect_multi_fire_next(struct event_context *ev, + struct timed_event *te, + struct timeval tv, void *p); + +struct composite_context *socket_connect_multi_send(TALLOC_CTX *mem_ctx, + const char *server_address, + int num_server_ports, + uint16_t *server_ports, + struct event_context *event_ctx) +{ + struct composite_context *result; + struct connect_multi_state *state; + int i; + + result = talloc_zero(mem_ctx, struct composite_context); + if (result == NULL) goto failed; + result->state = COMPOSITE_STATE_IN_PROGRESS; + result->event_ctx = event_ctx; + + state = talloc(result, struct connect_multi_state); + if (state == NULL) goto failed; + state->ctx = result; + result->private_data = state; + + state->server_address = talloc_strdup(state, server_address); + if (state->server_address == NULL) goto failed; + + state->num_ports = num_server_ports; + state->ports = talloc_array(state, uint16_t, state->num_ports); + if (state->ports == NULL) goto failed; + + for (i=0; i<state->num_ports; i++) { + state->ports[i] = server_ports[i]; + } + + state->sockets = + talloc_array(state, struct socket_context *, state->num_ports); + if (state->sockets == NULL) goto failed; + + state->write_events = + talloc_array(state, struct fd_event *, state->num_ports); + if (state->write_events == NULL) goto failed; + + state->num_connects_sent = 0; + state->num_connects_in_fly = 0; + + result->status = connect_multi_next_socket(state); + + if (!NT_STATUS_IS_OK(result->status)) { + composite_trigger_error(result); + return result; + } + + return result; + + failed: + talloc_free(result); + return NULL; +} + +static NTSTATUS connect_multi_next_socket(struct connect_multi_state *state) +{ + NTSTATUS status; + int res, next = state->num_connects_sent; + + status = socket_create("ipv4", SOCKET_TYPE_STREAM, + &state->sockets[next], 0); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + res = set_blocking(socket_get_fd(state->sockets[next]), False); + if (res != 0) { + return map_nt_error_from_unix(errno); + } + + talloc_steal(state->sockets, state->sockets[next]); + + status = socket_connect(state->sockets[next], NULL, 0, + state->server_address, state->ports[next], 0); + + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + return status; + } + + state->write_events[next] = + event_add_fd(state->ctx->event_ctx, state->write_events, + socket_get_fd(state->sockets[next]), + EVENT_FD_WRITE, + connect_multi_connect_handler, state); + + if (state->write_events[next] == NULL) { + return NT_STATUS_NO_MEMORY; + } + + state->num_connects_sent += 1; + state->num_connects_in_fly += 1; + + if (state->num_ports > state->num_connects_sent) { + state->next_timeout = + event_add_timed(state->ctx->event_ctx, state, + timeval_current_ofs(0, 2000), + connect_multi_fire_next, state); + if (state->next_timeout == NULL) { + talloc_free(state->sockets[next]); + state->sockets[next] = NULL; + talloc_free(state->write_events[next]); + state->write_events[next] = NULL; + return NT_STATUS_NO_MEMORY; + } + } + + return NT_STATUS_OK; +} + +static void connect_multi_fire_next(struct event_context *ev, + struct timed_event *te, + struct timeval tv, void *p) +{ + struct connect_multi_state *state = + talloc_get_type(p, struct connect_multi_state); + + state->ctx->status = connect_multi_next_socket(state); + if (!composite_is_ok(state->ctx)) return; +} + +static void connect_multi_connect_handler(struct event_context *ev, + struct fd_event *fde, + uint16_t flags, void *p) +{ + struct connect_multi_state *state = + talloc_get_type(p, struct connect_multi_state); + int i; + + for (i=0; i<state->num_connects_sent; i++) { + if (fde == state->write_events[i]) { + break; + } + } + + if (i == state->num_connects_sent) { + composite_error(state->ctx, NT_STATUS_INTERNAL_ERROR); + return; + } + + state->num_connects_in_fly -= 1; + + state->ctx->status = socket_connect_complete(state->sockets[i], 0); + if (NT_STATUS_IS_OK(state->ctx->status)) { + state->result = talloc_steal(state, state->sockets[i]); + state->result_port = state->ports[i]; + talloc_free(state->sockets); + state->sockets = NULL; + talloc_free(state->write_events); + state->write_events = NULL; + composite_done(state->ctx); + return; + } + + talloc_free(state->sockets[i]); + state->sockets[i] = NULL; + + if ((state->num_connects_in_fly == 0) && + (state->num_connects_sent == state->num_ports)) { + composite_error(state->ctx, state->ctx->status); + return; + } + + if (state->num_connects_in_fly != 0) { + /* Waiting for something to happen on the net or the next + * timeout to trigger */ + return; + } + + SMB_ASSERT(state->num_connects_sent < state->num_ports); + SMB_ASSERT(state->next_timeout != NULL); + + /* There are ports left but nothing on the net, so trigger the next + * one immediately. */ + talloc_free(state->next_timeout); + state->next_timeout = + event_add_timed(state->ctx->event_ctx, state, timeval_zero(), + connect_multi_fire_next, state); + if (composite_nomem(state->next_timeout, state->ctx)) return; +} + +NTSTATUS socket_connect_multi_recv(struct composite_context *ctx, + TALLOC_CTX *mem_ctx, + struct socket_context **result, + uint16_t *port) +{ + NTSTATUS status = composite_wait(ctx); + if (NT_STATUS_IS_OK(status)) { + struct connect_multi_state *state = + talloc_get_type(ctx->private_data, + struct connect_multi_state); + *result = talloc_steal(mem_ctx, state->result); + *port = state->result_port; + } + talloc_free(ctx); + return status; +} + +NTSTATUS socket_connect_multi(TALLOC_CTX *mem_ctx, + const char *server_address, + int num_server_ports, uint16_t *server_ports, + struct event_context *event_ctx, + struct socket_context **result, + uint16_t *result_port) +{ + struct composite_context *ctx = + socket_connect_multi_send(mem_ctx, server_address, + num_server_ports, server_ports, + event_ctx); + return socket_connect_multi_recv(ctx, mem_ctx, result, result_port); +} diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index 8b109a3a423..a79d698716f 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -153,4 +153,19 @@ NTSTATUS socket_connect_ev(struct socket_context *sock, const char *server_address, int server_port, uint32_t flags, struct event_context *ev); +struct composite_context *socket_connect_multi_send(TALLOC_CTX *mem_ctx, + const char *server_address, + int num_server_ports, + uint16_t *server_ports, + struct event_context *event_ctx); +NTSTATUS socket_connect_multi_recv(struct composite_context *ctx, + TALLOC_CTX *mem_ctx, + struct socket_context **result, + uint16_t *port); +NTSTATUS socket_connect_multi(TALLOC_CTX *mem_ctx, const char *server_address, + int num_server_ports, uint16_t *server_ports, + struct event_context *event_ctx, + struct socket_context **result, + uint16_t *port); + #endif /* _SAMBA_SOCKET_H */ diff --git a/source4/libcli/cliconnect.c b/source4/libcli/cliconnect.c index 00c50120747..c344ece3858 100644 --- a/source4/libcli/cliconnect.c +++ b/source4/libcli/cliconnect.c @@ -32,13 +32,9 @@ BOOL smbcli_socket_connect(struct smbcli_state *cli, const char *server) { struct smbcli_socket *sock; - sock = smbcli_sock_init(cli, NULL); - if (!sock) return False; + sock = smbcli_sock_connect_byname(server, 0, NULL, NULL); - if (!smbcli_sock_connect_byname(sock, server, 0)) { - talloc_free(sock); - return False; - } + if (sock == NULL) return False; cli->transport = smbcli_transport_init(sock, cli, True); if (!cli->transport) { diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk index 5ed4cff199c..c1747b5b17d 100644 --- a/source4/libcli/config.mk +++ b/source4/libcli/config.mk @@ -24,7 +24,6 @@ ADD_OBJ_FILES = \ smb_composite/loadfile.o \ smb_composite/savefile.o \ smb_composite/connect.o \ - smb_composite/connect_multi.o \ smb_composite/sesssetup.o \ smb_composite/fetchfile.o \ smb_composite/appendacl.o \ diff --git a/source4/libcli/ldap/ldap_client.c b/source4/libcli/ldap/ldap_client.c index d7cfd7c7e5c..3b801ca225f 100644 --- a/source4/libcli/ldap/ldap_client.c +++ b/source4/libcli/ldap/ldap_client.c @@ -428,17 +428,8 @@ struct composite_context *ldap_connect_send(struct ldap_connection *conn, return result; } - state->ctx->status = socket_create("ipv4", SOCKET_TYPE_STREAM, - &conn->sock, 0); - if (!NT_STATUS_IS_OK(state->ctx->status)) { - composite_trigger_error(state->ctx); - return result; - } - - talloc_steal(conn, conn->sock); - - ctx = socket_connect_send(conn->sock, NULL, 0, conn->host, - conn->port, 0, conn->event.event_ctx); + ctx = socket_connect_multi_send(state, conn->host, 1, &conn->port, + conn->event.event_ctx); if (ctx == NULL) goto failed; ctx->async.fn = ldap_connect_recv_conn; @@ -456,8 +447,10 @@ static void ldap_connect_recv_conn(struct composite_context *ctx) talloc_get_type(ctx->async.private_data, struct ldap_connect_state); struct ldap_connection *conn = state->conn; + uint16_t port; - state->ctx->status = socket_connect_recv(ctx); + state->ctx->status = socket_connect_multi_recv(ctx, state, &conn->sock, + &port); if (!composite_is_ok(state->ctx)) return; /* setup a handler for events on this socket */ diff --git a/source4/libcli/raw/clisocket.c b/source4/libcli/raw/clisocket.c index 688ee8a78b2..8b8a0b0fafd 100644 --- a/source4/libcli/raw/clisocket.c +++ b/source4/libcli/raw/clisocket.c @@ -27,206 +27,130 @@ #include "libcli/composite/composite.h" #include "lib/socket/socket.h" -/* - this private structure is used during async connection handling -*/ -struct clisocket_connect { - int port_num; - int *iports; - struct smbcli_socket *sock; - const char *dest_host_addr; - const char *dest_hostname; +struct sock_connect_state { + struct composite_context *ctx; + const char *host_name; + int num_ports; + uint16_t *ports; + struct smbcli_socket *result; }; - /* - create a smbcli_socket context - The event_ctx is optional - if not supplied one will be created + connect a smbcli_socket context to an IP/port pair + if port is 0 then choose 445 then 139 */ -struct smbcli_socket *smbcli_sock_init(TALLOC_CTX *mem_ctx, - struct event_context *event_ctx) + +static void smbcli_sock_connect_recv_conn(struct composite_context *ctx); + +struct composite_context *smbcli_sock_connect_send(TALLOC_CTX *mem_ctx, + const char *host_addr, + int port, + const char *host_name, + struct event_context *event_ctx) { - struct smbcli_socket *sock; + struct composite_context *result, *ctx; + struct sock_connect_state *state; - sock = talloc_zero(mem_ctx, struct smbcli_socket); - if (!sock) { - return NULL; - } + result = talloc_zero(mem_ctx, struct composite_context); + if (result == NULL) goto failed; + result->state = COMPOSITE_STATE_IN_PROGRESS; - if (event_ctx) { - sock->event.ctx = talloc_reference(sock, event_ctx); + if (event_ctx != NULL) { + result->event_ctx = talloc_reference(result, event_ctx); } else { - sock->event.ctx = event_context_init(sock); - } - if (sock->event.ctx == NULL) { - talloc_free(sock); - return NULL; + result->event_ctx = event_context_init(result); } - /* ensure we don't get SIGPIPE */ - BlockSignals(True,SIGPIPE); + if (result->event_ctx == NULL) goto failed; - return sock; -} + state = talloc(result, struct sock_connect_state); + if (state == NULL) goto failed; + state->ctx = result; + result->private_data = state; -static NTSTATUS smbcli_sock_connect_one(struct smbcli_socket *sock, - const char *hostaddr, int port, - struct composite_context *c); + state->host_name = talloc_strdup(state, host_name); + if (state->host_name == NULL) goto failed; -/* - handle socket write events during an async connect. These happen when the OS - has either completed the connect() or has returned an error -*/ -static void smbcli_sock_connect_handler(struct event_context *ev, struct fd_event *fde, - uint16_t flags, void *private_data) -{ - struct composite_context *c = talloc_get_type(private_data, struct composite_context); - struct clisocket_connect *conn = talloc_get_type(c->private_data, struct clisocket_connect); - int i; - - c->status = socket_connect_complete(conn->sock->sock, 0); - if (NT_STATUS_IS_OK(c->status)) { - socket_set_option(conn->sock->sock, lp_socket_options(), NULL); - conn->sock->hostname = talloc_strdup(conn->sock, conn->dest_hostname); - c->state = COMPOSITE_STATE_DONE; - if (c->async.fn) { - c->async.fn(c); - } - return; - } + if (port == 0) { + const char **ports = lp_smb_ports(); + int i; - /* that port failed - try the next port */ - for (i=conn->port_num+1;conn->iports[i];i++) { - conn->port_num = i; - c->status = smbcli_sock_connect_one(conn->sock, - conn->dest_host_addr, - conn->iports[i], c); - if (NT_STATUS_IS_OK(c->status) || - NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - return; + for (i=0;ports[i];i++) /* noop */ ; + if (i == 0) { + DEBUG(3, ("no smb ports defined\n")); + goto failed; } + state->num_ports = i; + state->ports = talloc_array(state, uint16_t, i); + if (state->ports == NULL) goto failed; + for (i=0;ports[i];i++) { + state->ports[i] = atoi(ports[i]); + } + } else { + state->ports = talloc_array(state, uint16_t, 1); + if (state->ports == NULL) goto failed; + state->num_ports = 1; + state->ports[0] = port; } - c->state = COMPOSITE_STATE_ERROR; - if (c->async.fn) { - c->async.fn(c); - } -} - - -/* - try to connect to the given address/port -*/ -static NTSTATUS smbcli_sock_connect_one(struct smbcli_socket *sock, - const char *hostaddr, int port, - struct composite_context *c) -{ - NTSTATUS status; - - if (sock->sock) { - talloc_free(sock->sock); - sock->sock = NULL; - } - talloc_free(sock->event.fde); - - status = socket_create("ip", SOCKET_TYPE_STREAM, &sock->sock, 0); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - talloc_steal(sock, sock->sock); - - /* we initially look for write - see the man page on - non-blocking connect */ - sock->event.fde = event_add_fd(sock->event.ctx, sock, socket_get_fd(sock->sock), - EVENT_FD_WRITE, smbcli_sock_connect_handler, c); + ctx = socket_connect_multi_send(state, host_addr, + state->num_ports, state->ports, + state->ctx->event_ctx); + if (ctx == NULL) goto failed; + ctx->async.fn = smbcli_sock_connect_recv_conn; + ctx->async.private_data = state; + return result; - sock->port = port; - set_blocking(socket_get_fd(sock->sock), False); - - return socket_connect(sock->sock, NULL, 0, hostaddr, port, 0); +failed: + talloc_free(result); + return NULL; } - -/* - connect a smbcli_socket context to an IP/port pair - if port is 0 then choose 445 then 139 - - this is the async send side of the interface -*/ -struct composite_context *smbcli_sock_connect_send(struct smbcli_socket *sock, - const char *host_addr, int port, - const char *host_name) +static void smbcli_sock_connect_recv_conn(struct composite_context *ctx) { - struct composite_context *c; - struct clisocket_connect *conn; - int i; + struct sock_connect_state *state = + talloc_get_type(ctx->async.private_data, + struct sock_connect_state); + struct socket_context *sock; + uint16_t port; - c = talloc_zero(sock, struct composite_context); - if (c == NULL) return NULL; + state->ctx->status = socket_connect_multi_recv(ctx, state, &sock, + &port); + if (!composite_is_ok(state->ctx)) return; - c->event_ctx = sock->event.ctx; + state->ctx->status = + socket_set_option(sock, lp_socket_options(), NULL); + if (!composite_is_ok(state->ctx)) return; - conn = talloc(c, struct clisocket_connect); - if (conn == NULL) goto failed; - conn->sock = sock; + state->result = talloc_zero(state, struct smbcli_socket); + if (composite_nomem(state->result, state->ctx)) return; - /* work out what ports we will try */ - if (port == 0) { - const char **ports = lp_smb_ports(); - for (i=0;ports[i];i++) /* noop */ ; - conn->iports = talloc_array(c, int, i+1); - if (conn->iports == NULL) goto failed; - for (i=0;ports[i];i++) { - conn->iports[i] = atoi(ports[i]); - } - conn->iports[i] = 0; - } else { - conn->iports = talloc_array(c, int, 2); - if (conn->iports == NULL) goto failed; - conn->iports[0] = port; - conn->iports[1] = 0; - } + state->result->sock = talloc_steal(state->result, sock); + state->result->port = port; + state->result->hostname = talloc_steal(sock, state->host_name); - conn->dest_host_addr = talloc_strdup(c, host_addr); - if (conn->dest_host_addr == NULL) goto failed; - - conn->dest_hostname = talloc_strdup(c, host_name); - if (conn->dest_hostname == NULL) goto failed; - - c->private_data = conn; - c->state = COMPOSITE_STATE_IN_PROGRESS; - - /* startup the connect process for each port in turn until one - succeeds or tells us that it is pending */ - for (i=0;conn->iports[i];i++) { - conn->port_num = i; - conn->sock->port = conn->iports[i]; - c->status = smbcli_sock_connect_one(sock, - conn->dest_host_addr, - conn->iports[i], c); - if (NT_STATUS_IS_OK(c->status) || - NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - return c; - } - } + state->result->event.ctx = + talloc_reference(state->result, state->ctx->event_ctx); + if (composite_nomem(state->result->event.ctx, state->ctx)) return; - c->state = COMPOSITE_STATE_ERROR; - return c; - -failed: - talloc_free(c); - return NULL; + composite_done(state->ctx); } /* finish a smbcli_sock_connect_send() operation */ -NTSTATUS smbcli_sock_connect_recv(struct composite_context *c) +NTSTATUS smbcli_sock_connect_recv(struct composite_context *c, + TALLOC_CTX *mem_ctx, + struct smbcli_socket **result) { - NTSTATUS status; - status = composite_wait(c); + NTSTATUS status = composite_wait(c); + if (NT_STATUS_IS_OK(status)) { + struct sock_connect_state *state = + talloc_get_type(c->private_data, + struct sock_connect_state); + *result = talloc_steal(mem_ctx, state->result); + } talloc_free(c); return status; } @@ -237,17 +161,16 @@ NTSTATUS smbcli_sock_connect_recv(struct composite_context *c) sync version of the function */ -NTSTATUS smbcli_sock_connect(struct smbcli_socket *sock, const char *host_addr, int port, - const char *host_name) +NTSTATUS smbcli_sock_connect(TALLOC_CTX *mem_ctx, + const char *host_addr, int port, + const char *host_name, + struct event_context *event_ctx, + struct smbcli_socket **result) { - struct composite_context *c; - - c = smbcli_sock_connect_send(sock, host_addr, port, host_name); - if (c == NULL) { - return NT_STATUS_NO_MEMORY; - } - - return smbcli_sock_connect_recv(c); + struct composite_context *c = + smbcli_sock_connect_send(mem_ctx, host_addr, port, host_name, + event_ctx); + return smbcli_sock_connect_recv(c, mem_ctx, result); } @@ -306,15 +229,39 @@ NTSTATUS smbcli_sock_read(struct smbcli_socket *sock, uint8_t *data, /**************************************************************************** resolve a hostname and connect ****************************************************************************/ -BOOL smbcli_sock_connect_byname(struct smbcli_socket *sock, const char *host, int port) +struct smbcli_socket *smbcli_sock_connect_byname(const char *host, int port, + TALLOC_CTX *mem_ctx, + struct event_context *event_ctx) { int name_type = NBT_NAME_SERVER; const char *address; NTSTATUS status; struct nbt_name nbt_name; char *name, *p; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + struct smbcli_socket *result; + + if (tmp_ctx == NULL) { + DEBUG(0, ("talloc_new failed\n")); + return NULL; + } + + name = talloc_strdup(tmp_ctx, host); + if (name == NULL) { + DEBUG(0, ("talloc_strdup failed\n")); + talloc_free(tmp_ctx); + return NULL; + } + + if (event_ctx == NULL) { + event_ctx = event_context_init(mem_ctx); + } - name = talloc_strdup(sock, host); + if (event_ctx == NULL) { + DEBUG(0, ("event_context_init failed\n")); + talloc_free(tmp_ctx); + return NULL; + } /* allow hostnames of the form NAME#xx and do a netbios lookup */ if ((p = strchr(name, '#'))) { @@ -322,16 +269,25 @@ BOOL smbcli_sock_connect_byname(struct smbcli_socket *sock, const char *host, in *p = 0; } - nbt_name.name = name; - nbt_name.type = name_type; - nbt_name.scope = NULL; + make_nbt_name(&nbt_name, host, name_type); - status = resolve_name(&nbt_name, sock, &address, sock->event.ctx); + status = resolve_name(&nbt_name, tmp_ctx, &address, event_ctx); if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); return False; } - status = smbcli_sock_connect(sock, address, port, name); + status = smbcli_sock_connect(mem_ctx, address, port, name, event_ctx, + &result); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(9, ("smbcli_sock_connect failed: %s\n", + nt_errstr(status))); + talloc_free(tmp_ctx); + return NULL; + } + + talloc_free(tmp_ctx); - return NT_STATUS_IS_OK(status); + return result; } diff --git a/source4/libcli/smb_composite/connect.c b/source4/libcli/smb_composite/connect.c index 4e9ee48cb76..643871a8c4e 100644 --- a/source4/libcli/smb_composite/connect.c +++ b/source4/libcli/smb_composite/connect.c @@ -41,7 +41,6 @@ struct connect_state { struct smbcli_socket *sock; struct smbcli_transport *transport; struct smbcli_session *session; - struct smb_composite_connectmulti *conn; struct smb_composite_connect *io; union smb_tcon *io_tcon; struct smb_composite_sesssetup *io_setup; @@ -73,7 +72,7 @@ static NTSTATUS connect_send_negprot(struct composite_context *c, /* - a tree connect request has competed + a tree connect request has completed */ static NTSTATUS connect_tcon(struct composite_context *c, struct smb_composite_connect *io) @@ -232,7 +231,7 @@ static NTSTATUS connect_session_setup(struct composite_context *c, } /* - a negprot request has competed + a negprot request has completed */ static NTSTATUS connect_negprot(struct composite_context *c, struct smb_composite_connect *io) @@ -271,7 +270,7 @@ static NTSTATUS connect_negprot(struct composite_context *c, /* - a session request operation has competed + a session request operation has completed */ static NTSTATUS connect_session_request(struct composite_context *c, struct smb_composite_connect *io) @@ -287,7 +286,7 @@ static NTSTATUS connect_session_request(struct composite_context *c, } /* - a socket connection operation has competed + a socket connection operation has completed */ static NTSTATUS connect_socket(struct composite_context *c, struct smb_composite_connect *io) @@ -296,11 +295,9 @@ static NTSTATUS connect_socket(struct composite_context *c, NTSTATUS status; struct nbt_name calling, called; - status = smb_composite_connectmulti_recv(state->creq, state); + status = smbcli_sock_connect_recv(state->creq, state, &state->sock); NT_STATUS_NOT_OK_RETURN(status); - state->sock = state->conn->out.socket; - /* the socket is up - we can initialise the smbcli transport layer */ state->transport = smbcli_transport_init(state->sock, state, True); NT_STATUS_HAVE_NO_MEMORY(state->transport); @@ -339,37 +336,12 @@ static NTSTATUS connect_resolve(struct composite_context *c, struct connect_state *state = talloc_get_type(c->private_data, struct connect_state); NTSTATUS status; const char *address; - struct smb_composite_connectmulti *conn; status = resolve_name_recv(state->creq, state, &address); NT_STATUS_NOT_OK_RETURN(status); - conn = talloc(state, struct smb_composite_connectmulti); - NT_STATUS_HAVE_NO_MEMORY(conn); - state->conn = conn; - conn->in.num_dests = 1; - - conn->in.addresses = talloc_array(state->conn, const char *, 1); - NT_STATUS_HAVE_NO_MEMORY(conn->in.addresses); - conn->in.addresses[0] = address; - - conn->in.hostnames = talloc_array(state->conn, const char *, 1); - NT_STATUS_HAVE_NO_MEMORY(conn->in.hostnames); - if (state->io->in.called_name != NULL) { - conn->in.hostnames[0] = state->io->in.called_name; - } else { - conn->in.hostnames[0] = state->io->in.dest_host; - } - - conn->in.ports = NULL; - if (state->io->in.port != 0) { - conn->in.ports = talloc_array(state->conn, int, 1); - NT_STATUS_HAVE_NO_MEMORY(conn->in.ports); - conn->in.ports[0] = state->io->in.port; - } - - state->creq = smb_composite_connectmulti_send(conn, state, - c->event_ctx); + state->creq = smbcli_sock_connect_send(state, address, io->in.port, + io->in.dest_host, c->event_ctx); NT_STATUS_HAVE_NO_MEMORY(state->creq); state->stage = CONNECT_SOCKET; diff --git a/source4/libcli/smb_composite/connect_multi.c b/source4/libcli/smb_composite/connect_multi.c deleted file mode 100644 index a539ba4bc62..00000000000 --- a/source4/libcli/smb_composite/connect_multi.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Copyright (C) Volker Lendecke - - 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. -*/ -/* - a composite API to fire connect calls to multiple targets, picking the first - one. -*/ - -#include "includes.h" -#include "libcli/raw/libcliraw.h" -#include "libcli/composite/composite.h" -#include "libcli/smb_composite/smb_composite.h" - -struct connectmulti_state { - struct smb_composite_connectmulti *io; - struct composite_context *creq; - struct smbcli_socket *result; - int num_socks, socks_left; - struct smbcli_socket **socks; - struct composite_context **creqs; -}; - -static void connect_receive(struct composite_context *c) - -{ - struct connectmulti_state *state = - talloc_get_type(c->async.private_data, - struct connectmulti_state); - int i; - - for (i=0; i<state->num_socks; i++) { - if (state->creqs[i] == c) { - break; - } - } - - if (i == state->num_socks) { - c->status = NT_STATUS_INTERNAL_ERROR; - c->state = COMPOSITE_STATE_ERROR; - if (state->creq->async.fn != NULL) { - state->creq->async.fn(state->creq); - } - return; - } - - state->creq->status = smbcli_sock_connect_recv(c); - if (!NT_STATUS_IS_OK(state->creq->status)) { - talloc_free(state->socks[i]); - state->socks[i] = NULL; - state->creqs[i] = NULL; - state->socks_left -= 1; - if (state->socks_left == 0) { - state->creq->state = COMPOSITE_STATE_ERROR; - if (state->creq->async.fn != NULL) { - state->creq->async.fn(state->creq); - } - } - return; - } - - state->result = talloc_steal(state, state->socks[i]); - talloc_free(state->socks); - - state->creq->state = COMPOSITE_STATE_DONE; - if (state->creq->async.fn != NULL) { - state->creq->async.fn(state->creq); - } -} - -struct composite_context *smb_composite_connectmulti_send(struct smb_composite_connectmulti *io, - TALLOC_CTX *mem_ctx, - struct event_context *event_ctx) -{ - struct composite_context *c; - struct connectmulti_state *state; - int num_socks = io->in.num_dests; - const char **hostnames = io->in.hostnames; - const char **addresses = io->in.addresses; - int *ports = io->in.ports; - int i; - - c = talloc_zero(mem_ctx, struct composite_context); - if (c == NULL) goto failed; - - state = talloc(c, struct connectmulti_state); - if (state == NULL) goto failed; - - c->state = COMPOSITE_STATE_IN_PROGRESS; - c->event_ctx = talloc_reference(c, event_ctx); - c->private_data = state; - - if (ports == NULL) { - int j, nports; - const char **smb_ports = lp_smb_ports(); - - for (nports=0; smb_ports[nports]; nports++) /* noop */; - - num_socks *= nports; - hostnames = talloc_array(state, const char *, num_socks); - if (hostnames == NULL) goto failed; - addresses = talloc_array(state, const char *, num_socks); - if (addresses == NULL) goto failed; - ports = talloc_array(state, int, num_socks); - if (ports == NULL) goto failed; - - for (i=0; i<io->in.num_dests; i++) { - for (j=0; j<nports; j++) { - hostnames[i*nports+j] = io->in.hostnames[i]; - addresses[i*nports+j] = io->in.addresses[i]; - ports[i*nports+j] = atoi(smb_ports[j]); - } - } - } - - state->io = io; - state->creq = c; - state->num_socks = num_socks; - state->socks_left = num_socks; - state->socks = talloc_array(state, struct smbcli_socket *, num_socks); - state->creqs = talloc_array(state, struct composite_context *, - num_socks); - if ((state->socks == NULL) || (state->creqs == NULL)) goto failed; - - for (i=0; i<num_socks; i++) { - state->socks[i] = smbcli_sock_init(state->socks, event_ctx); - if (state->socks[i] == NULL) goto failed; - - /* If the event_ctx we got given is NULL, the first socket - * creates one and all others need to refer to it. */ - event_ctx = state->socks[i]->event.ctx; - - state->creqs[i] = smbcli_sock_connect_send(state->socks[i], - addresses[i], - ports[i], - hostnames[i]); - if (state->creqs[i] == NULL) goto failed; - state->creqs[i]->async.fn = connect_receive; - state->creqs[i]->async.private_data = state; - } - - return c; - - failed: - talloc_free(c); - return NULL; -} - -NTSTATUS smb_composite_connectmulti_recv(struct composite_context *c, - TALLOC_CTX *mem_ctx) -{ - NTSTATUS status; - status = composite_wait(c); - - if (NT_STATUS_IS_OK(status)) { - struct connectmulti_state *state = - talloc_get_type(c->private_data, - struct connectmulti_state); - state->io->out.socket = talloc_steal(mem_ctx, state->result); - } - - talloc_free(c); - return status; -} - -NTSTATUS smb_composite_connectmulti(struct smb_composite_connectmulti *io, - TALLOC_CTX *mem_ctx, - struct event_context *ev) -{ - struct composite_context *c = - smb_composite_connectmulti_send(io, mem_ctx, ev); - return smb_composite_connectmulti_recv(c, mem_ctx); -} |