The branch, v3-2-test has been updated via 5c7f7629a97ef0929e00e52f1fae4386c984000b (commit) from aabe9b33fcaed8af98b1ed6b736253e196d87d48 (commit)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-2-test - Log ----------------------------------------------------------------- commit 5c7f7629a97ef0929e00e52f1fae4386c984000b Author: Jeremy Allison <[EMAIL PROTECTED]> Date: Wed Dec 12 09:42:58 2007 -0800 Allow cliconnect to loop through multiple ip addresses for a server. We should have been doing this for a while, but it's more critical with IPv6. Original patch fixed up by James. Jeremy. ----------------------------------------------------------------------- Summary of changes: source/libsmb/cliconnect.c | 72 ++++++++++++++++++++++++++------------ source/libsmb/namequery.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 23 deletions(-) Changeset truncated at 500 lines: diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c index fdf7491..45c2020 100644 --- a/source/libsmb/cliconnect.c +++ b/source/libsmb/cliconnect.c @@ -1424,7 +1424,11 @@ NTSTATUS cli_connect(struct cli_state *cli, { int name_type = 0x20; - char *p; + TALLOC_CTX *frame = talloc_stackframe(); + unsigned int num_addrs = 0; + unsigned int i = 0; + struct sockaddr_storage *ss_arr = NULL; + char *p = NULL; /* reasonable default hostname */ if (!host) { @@ -1440,44 +1444,66 @@ NTSTATUS cli_connect(struct cli_state *cli, } if (!dest_ss || is_zero_addr(dest_ss)) { - if (!resolve_name(cli->desthost, &cli->dest_ss, name_type)) { + NTSTATUS status =resolve_name_list(frame, + cli->desthost, + name_type, + &ss_arr, + &num_addrs); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); return NT_STATUS_BAD_NETWORK_NAME; } - if (dest_ss) { - *dest_ss = cli->dest_ss; - } } else { - cli->dest_ss = *dest_ss; + num_addrs = 1; + ss_arr = TALLOC_P(frame, struct sockaddr_storage); + if (!ss_arr) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + *ss_arr = *dest_ss; } - if (getenv("LIBSMB_PROG")) { - cli->fd = sock_exec(getenv("LIBSMB_PROG")); - } else { - /* try 445 first, then 139 */ - uint16_t port = cli->port?cli->port:445; - cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ss, - port, cli->timeout); - if (cli->fd == -1 && cli->port == 0) { - port = 139; + for (i = 0; i < num_addrs; i++) { + cli->dest_ss = ss_arr[i]; + if (getenv("LIBSMB_PROG")) { + cli->fd = sock_exec(getenv("LIBSMB_PROG")); + } else { + /* try 445 first, then 139 */ + uint16_t port = cli->port?cli->port:445; cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ss, port, cli->timeout); + if (cli->fd == -1 && cli->port == 0) { + port = 139; + cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ss, + port, cli->timeout); + } + if (cli->fd != -1) { + cli->port = port; + } } - if (cli->fd != -1) { - cli->port = port; + if (cli->fd == -1) { + char addr[INET6_ADDRSTRLEN]; + print_sockaddr(addr, sizeof(addr), &ss_arr[i]); + DEBUG(2,("Error connecting to %s (%s)\n", + dest_ss?addr:host,strerror(errno))); + } else { + /* Exit from loop on first connection. */ + break; } } + if (cli->fd == -1) { - char addr[INET6_ADDRSTRLEN]; - if (dest_ss) { - print_sockaddr(addr, sizeof(addr), dest_ss); - } - DEBUG(1,("Error connecting to %s (%s)\n", - dest_ss?addr:host,strerror(errno))); + TALLOC_FREE(frame); return map_nt_error_from_unix(errno); } + if (dest_ss) { + *dest_ss = cli->dest_ss; + } + set_socket_options(cli->fd, lp_socket_options()); + TALLOC_FREE(frame); return NT_STATUS_OK; } diff --git a/source/libsmb/namequery.c b/source/libsmb/namequery.c index 819147d..853fe97 100644 --- a/source/libsmb/namequery.c +++ b/source/libsmb/namequery.c @@ -1654,6 +1654,87 @@ bool resolve_name(const char *name, } /******************************************************** + Internal interface to resolve a name into a list of IP addresses. + Use this function if the string is either an IP address, DNS + or host name or NetBIOS name. This uses the name switch in the + smb.conf to determine the order of name resolution. +*********************************************************/ + +NTSTATUS resolve_name_list(TALLOC_CTX *ctx, + const char *name, + int name_type, + struct sockaddr_storage **return_ss_arr, + unsigned int *p_num_entries) +{ + struct ip_service *ss_list = NULL; + char *sitename = NULL; + int count = 0; + int i; + unsigned int num_entries; + NTSTATUS status; + + *p_num_entries = 0; + *return_ss_arr = NULL; + + if (is_ipaddress(name)) { + *return_ss_arr = TALLOC_P(ctx, struct sockaddr_storage); + if (!*return_ss_arr) { + return NT_STATUS_NO_MEMORY; + } + if (!interpret_string_addr(*return_ss_arr, name, AI_NUMERICHOST)) { + TALLOC_FREE(*return_ss_arr); + return NT_STATUS_BAD_NETWORK_NAME; + } + *p_num_entries = 1; + return NT_STATUS_OK; + } + + sitename = sitename_fetch(lp_realm()); /* wild guess */ + + status = internal_resolve_name(name, name_type, sitename, + &ss_list, &count, + lp_name_resolve_order()); + SAFE_FREE(sitename); + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* only return valid addresses for TCP connections */ + for (i=0, num_entries = 0; i<count; i++) { + if (!is_zero_addr(&ss_list[i].ss) && + !is_broadcast_addr(&ss_list[i].ss)) { + num_entries++; + } + } + if (num_entries == 0) { + SAFE_FREE(ss_list); + return NT_STATUS_BAD_NETWORK_NAME; + } + + *return_ss_arr = TALLOC_ARRAY(ctx, + struct sockaddr_storage, + num_entries); + if (!(*return_ss_arr)) { + SAFE_FREE(ss_list); + return NT_STATUS_NO_MEMORY; + } + + for (i=0, num_entries = 0; i<count; i++) { + if (!is_zero_addr(&ss_list[i].ss) && + !is_broadcast_addr(&ss_list[i].ss)) { + (*return_ss_arr)[num_entries++] = ss_list[i].ss; + } + } + + status = NT_STATUS_OK; + *p_num_entries = num_entries; + + SAFE_FREE(ss_list); + return NT_STATUS_OK; +} + +/******************************************************** Find the IP address of the master browser or DMB for a workgroup. *********************************************************/ -- Samba Shared Repository