mirror of
				https://github.com/samba-team/samba.git
				synced 2025-11-04 00:23:49 +03:00 
			
		
		
		
	r10677: Add smb_composite_connectmulti: Send out multiple SYN packets at once, use the
first one that replies correctly. Add a talloc context to smb_composite_connect() Volker
This commit is contained in:
		
				
					committed by
					
						
						Gerald (Jerry) Carter
					
				
			
			
				
	
			
			
			
						parent
						
							c755788484
						
					
				
				
					commit
					6b88de182e
				
			@@ -217,6 +217,7 @@ struct monitor_msg;
 | 
			
		||||
struct smb_composite_loadfile;
 | 
			
		||||
struct smb_composite_savefile;
 | 
			
		||||
struct smb_composite_connect;
 | 
			
		||||
struct smb_composite_connectmulti;
 | 
			
		||||
struct smb_composite_sesssetup;
 | 
			
		||||
struct smb_composite_fetchfile;
 | 
			
		||||
struct smb_composite_appendacl;
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@ ADD_OBJ_FILES = \
 | 
			
		||||
	libcli/smb_composite/loadfile.o \
 | 
			
		||||
	libcli/smb_composite/savefile.o \
 | 
			
		||||
	libcli/smb_composite/connect.o \
 | 
			
		||||
	libcli/smb_composite/connect_multi.o \
 | 
			
		||||
	libcli/smb_composite/sesssetup.o \
 | 
			
		||||
	libcli/smb_composite/fetchfile.o \
 | 
			
		||||
	libcli/smb_composite/appendacl.o \
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@
 | 
			
		||||
#include "libcli/raw/libcliraw.h"
 | 
			
		||||
#include "libcli/composite/composite.h"
 | 
			
		||||
#include "libcli/smb_composite/smb_composite.h"
 | 
			
		||||
#include "lib/events/events.h"
 | 
			
		||||
 | 
			
		||||
/* the stages of this call */
 | 
			
		||||
enum connect_stage {CONNECT_RESOLVE, 
 | 
			
		||||
@@ -39,6 +40,7 @@ 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;
 | 
			
		||||
@@ -213,9 +215,11 @@ static NTSTATUS connect_socket(struct composite_context *c,
 | 
			
		||||
	NTSTATUS status;
 | 
			
		||||
	struct nbt_name calling, called;
 | 
			
		||||
 | 
			
		||||
	status = smbcli_sock_connect_recv(state->creq);
 | 
			
		||||
	status = smb_composite_connectmulti_recv(state->creq, state);
 | 
			
		||||
	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);
 | 
			
		||||
@@ -254,11 +258,33 @@ 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);
 | 
			
		||||
 | 
			
		||||
	state->creq = smbcli_sock_connect_send(state->sock, address, state->io->in.port, io->in.dest_host);
 | 
			
		||||
	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);
 | 
			
		||||
	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);
 | 
			
		||||
	NT_STATUS_HAVE_NO_MEMORY(state->creq);
 | 
			
		||||
 | 
			
		||||
	state->stage = CONNECT_SOCKET;
 | 
			
		||||
@@ -332,25 +358,27 @@ static void composite_handler(struct composite_context *creq)
 | 
			
		||||
  a function to establish a smbcli_tree from scratch
 | 
			
		||||
*/
 | 
			
		||||
struct composite_context *smb_composite_connect_send(struct smb_composite_connect *io,
 | 
			
		||||
						    struct event_context *event_ctx)
 | 
			
		||||
						     TALLOC_CTX *mem_ctx,
 | 
			
		||||
						     struct event_context *event_ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct composite_context *c;
 | 
			
		||||
	struct connect_state *state;
 | 
			
		||||
	struct nbt_name name;
 | 
			
		||||
 | 
			
		||||
	c = talloc_zero(NULL, struct composite_context);
 | 
			
		||||
	c = talloc_zero(mem_ctx, struct composite_context);
 | 
			
		||||
	if (c == NULL) goto failed;
 | 
			
		||||
 | 
			
		||||
	state = talloc(c, struct connect_state);
 | 
			
		||||
	if (state == NULL) goto failed;
 | 
			
		||||
 | 
			
		||||
	state->sock = smbcli_sock_init(state, event_ctx);
 | 
			
		||||
	if (state->sock == NULL) goto failed;
 | 
			
		||||
	if (event_ctx == NULL) {
 | 
			
		||||
		event_ctx = event_context_init(mem_ctx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	state->io = io;
 | 
			
		||||
 | 
			
		||||
	c->state = COMPOSITE_STATE_IN_PROGRESS;
 | 
			
		||||
	c->event_ctx = talloc_reference(c, state->sock->event.ctx);
 | 
			
		||||
	c->event_ctx = talloc_reference(c, event_ctx);
 | 
			
		||||
	c->private_data = state;
 | 
			
		||||
 | 
			
		||||
	state->stage = CONNECT_RESOLVE;
 | 
			
		||||
@@ -391,6 +419,6 @@ NTSTATUS smb_composite_connect_recv(struct composite_context *c, TALLOC_CTX *mem
 | 
			
		||||
NTSTATUS smb_composite_connect(struct smb_composite_connect *io, TALLOC_CTX *mem_ctx,
 | 
			
		||||
			       struct event_context *ev)
 | 
			
		||||
{
 | 
			
		||||
	struct composite_context *c = smb_composite_connect_send(io, ev);
 | 
			
		||||
	struct composite_context *c = smb_composite_connect_send(io, mem_ctx, ev);
 | 
			
		||||
	return smb_composite_connect_recv(c, mem_ctx);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										188
									
								
								source/libcli/smb_composite/connect_multi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								source/libcli/smb_composite/connect_multi.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,188 @@
 | 
			
		||||
/* 
 | 
			
		||||
   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);
 | 
			
		||||
}
 | 
			
		||||
@@ -146,7 +146,7 @@ struct composite_context *smb_composite_fetchfile_send(struct smb_composite_fetc
 | 
			
		||||
	state->connect->in.credentials  = io->in.credentials;
 | 
			
		||||
	state->connect->in.workgroup    = io->in.workgroup;
 | 
			
		||||
 | 
			
		||||
	state->creq = smb_composite_connect_send(state->connect, event_ctx);
 | 
			
		||||
	state->creq = smb_composite_connect_send(state->connect, state, event_ctx);
 | 
			
		||||
	if (state->creq == NULL) goto failed;
 | 
			
		||||
 | 
			
		||||
	state->creq->async.private_data = c;
 | 
			
		||||
 
 | 
			
		||||
@@ -156,7 +156,8 @@ struct composite_context *smb_composite_fsinfo_send(struct smbcli_tree *tree,
 | 
			
		||||
	c->event_ctx = talloc_reference(c,  tree->session->transport->socket->event.ctx);
 | 
			
		||||
	c->private_data = state;
 | 
			
		||||
 | 
			
		||||
	state->creq = smb_composite_connect_send(state->connect, c->event_ctx);
 | 
			
		||||
	state->creq = smb_composite_connect_send(state->connect, state,
 | 
			
		||||
						 c->event_ctx);
 | 
			
		||||
 | 
			
		||||
	if (state->creq == NULL) goto failed;
 | 
			
		||||
  
 | 
			
		||||
 
 | 
			
		||||
@@ -150,3 +150,21 @@ struct smb_composite_appendacl {
 | 
			
		||||
		struct security_descriptor *sd;
 | 
			
		||||
	} out;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  a composite API to fire connect() calls to multiple targets, picking the
 | 
			
		||||
  first one.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
struct smb_composite_connectmulti {
 | 
			
		||||
	struct {
 | 
			
		||||
		int num_dests;
 | 
			
		||||
		const char **hostnames;
 | 
			
		||||
		const char **addresses;
 | 
			
		||||
		int *ports; 	/* Either NULL for lp_smb_ports() per
 | 
			
		||||
				 * destination or a list of explicit ports */
 | 
			
		||||
	} in;
 | 
			
		||||
	struct {
 | 
			
		||||
		struct smbcli_socket *socket;
 | 
			
		||||
	} out;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -134,7 +134,7 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs,
 | 
			
		||||
	io.in.service = remote_share;
 | 
			
		||||
	io.in.service_type = "?????";
 | 
			
		||||
	
 | 
			
		||||
	creq = smb_composite_connect_send(&io, tcon->smb_conn->connection->event.ctx);
 | 
			
		||||
	creq = smb_composite_connect_send(&io, private, tcon->smb_conn->connection->event.ctx);
 | 
			
		||||
	status = smb_composite_connect_recv(creq, private);
 | 
			
		||||
	NT_STATUS_NOT_OK_RETURN(status);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -164,7 +164,8 @@ static void wbsrv_samba3_check_machacc_receive_dcs(struct composite_context *act
 | 
			
		||||
	cli_credentials_set_conf(state->conn->in.credentials);
 | 
			
		||||
	cli_credentials_set_anonymous(state->conn->in.credentials);
 | 
			
		||||
 | 
			
		||||
	ctx = smb_composite_connect_send(state->conn, s3call->call->event_ctx);
 | 
			
		||||
	ctx = smb_composite_connect_send(state->conn, state,
 | 
			
		||||
					 s3call->call->event_ctx);
 | 
			
		||||
	if (ctx == NULL) {
 | 
			
		||||
		status = NT_STATUS_NO_MEMORY;
 | 
			
		||||
		goto done;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user