MDEV-24377: Accept comma separated addresses as --bind-address value (#2009)
* MDEV-24377: Accept comma separated addresses as --bind-address value When bind address form the basis of wsrep based variables, the first address in the comma separated list is used. The test uses the IP address 192.168.0.1 as we need to include multiple address. This will include failures without the following commit. The tests for bind_multiple_address_resolution could return addresses that we cannot bind too. Windows and FreeBSD, and probably other OSs will terminate the service if addresses are unavailable. We use the WSAEADDRNOTAVAIL / POSIX EADDRNOTAVAIL codes to continue to bind to other interfaces. If at the end of the bind list, if no binds are successful, the we terminate but still leaving the error messages in the log. Co-authored-by: Daniel Black <daniel@mariadb.org>
This commit is contained in:
parent
fd0dcad676
commit
ba16202e78
1
mysql-test/main/bind_multiple_addresses_resolution.opt
Normal file
1
mysql-test/main/bind_multiple_addresses_resolution.opt
Normal file
@ -0,0 +1 @@
|
||||
--bind-address=localhost,192.168.0.1
|
12
mysql-test/main/bind_multiple_addresses_resolution.result
Normal file
12
mysql-test/main/bind_multiple_addresses_resolution.result
Normal file
@ -0,0 +1,12 @@
|
||||
call mtr.add_suppression("Can't start server: Bind on TCP/IP port.");
|
||||
CREATE TABLE t (a TEXT);
|
||||
connect con1,localhost,root,,test;
|
||||
SELECT * FROM t;
|
||||
a
|
||||
connect con2,127.0.0.1,root,,test;
|
||||
SELECT * FROM t;
|
||||
a
|
||||
connection default;
|
||||
DROP TABLE t;
|
||||
disconnect con1;
|
||||
disconnect con2;
|
23
mysql-test/main/bind_multiple_addresses_resolution.test
Normal file
23
mysql-test/main/bind_multiple_addresses_resolution.test
Normal file
@ -0,0 +1,23 @@
|
||||
--source include/check_ipv6.inc
|
||||
--source include/not_embedded.inc
|
||||
|
||||
call mtr.add_suppression("Can't start server: Bind on TCP/IP port.");
|
||||
# The server is started with --bind-address=localhost,192.168.0.1, and should
|
||||
# listen on all addresses 'localhost' resolves to and 192.168.0.1. With at least
|
||||
# 127.0.0.1 and ::1 amongst them.
|
||||
|
||||
CREATE TABLE t (a TEXT);
|
||||
--connect(con1,localhost,root,,test)
|
||||
SELECT * FROM t;
|
||||
--connect(con2,127.0.0.1,root,,test)
|
||||
SELECT * FROM t;
|
||||
# Temporary disable.
|
||||
# Some cloud-init services don't resolve localhost->::1
|
||||
# bb - kvm-asan, kvm-deb-focal-amd64, kvm-deb-groovy-amd64
|
||||
#--connect(con3,::1,root,,test)
|
||||
#SELECT * FROM t;
|
||||
--connection default
|
||||
DROP TABLE t;
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
#--disconnect con3
|
@ -42,7 +42,8 @@ The following specify which files/extra groups are read (specified before remain
|
||||
by saving all temporary sets to disk, avoiding 'table
|
||||
full' errors. No longer needed, as the server now handles
|
||||
this automatically.
|
||||
--bind-address=name IP address to bind to.
|
||||
--bind-address=name IP address to bind to. Several addresses may be
|
||||
specified, separated by a comma (,).
|
||||
--binlog-alter-two-phase
|
||||
When set, split ALTER at binary logging into 2
|
||||
statements: START ALTER and COMMIT/ROLLBACK ALTER
|
||||
|
@ -325,7 +325,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL
|
||||
VARIABLE_NAME BIND_ADDRESS
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE VARCHAR
|
||||
VARIABLE_COMMENT IP address to bind to.
|
||||
VARIABLE_COMMENT IP address to bind to. Several addresses may be specified, separated by a comma (,).
|
||||
NUMERIC_MIN_VALUE NULL
|
||||
NUMERIC_MAX_VALUE NULL
|
||||
NUMERIC_BLOCK_SIZE NULL
|
||||
|
@ -325,7 +325,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL
|
||||
VARIABLE_NAME BIND_ADDRESS
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE VARCHAR
|
||||
VARIABLE_COMMENT IP address to bind to.
|
||||
VARIABLE_COMMENT IP address to bind to. Several addresses may be specified, separated by a comma (,).
|
||||
NUMERIC_MIN_VALUE NULL
|
||||
NUMERIC_MAX_VALUE NULL
|
||||
NUMERIC_BLOCK_SIZE NULL
|
||||
|
@ -135,7 +135,6 @@
|
||||
|
||||
#define mysqld_charset &my_charset_latin1
|
||||
|
||||
|
||||
extern "C" { // Because of SCO 3.2V4.2
|
||||
#include <sys/stat.h>
|
||||
#ifndef __GNU_LIBRARY__
|
||||
@ -2291,7 +2290,7 @@ static void activate_tcp_port(uint port,
|
||||
Dynamic_array<MYSQL_SOCKET> *sockets,
|
||||
bool is_extra_port= false)
|
||||
{
|
||||
struct addrinfo *ai, *a;
|
||||
struct addrinfo *ai, *a = NULL, *head = NULL;
|
||||
struct addrinfo hints;
|
||||
int error;
|
||||
int arg;
|
||||
@ -2312,16 +2311,52 @@ static void activate_tcp_port(uint port,
|
||||
real_bind_addr_str= my_bind_addr_str;
|
||||
|
||||
my_snprintf(port_buf, NI_MAXSERV, "%d", port);
|
||||
error= getaddrinfo(real_bind_addr_str, port_buf, &hints, &ai);
|
||||
if (unlikely(error != 0))
|
||||
{
|
||||
DBUG_PRINT("error",("Got error: %d from getaddrinfo()", error));
|
||||
|
||||
sql_print_error("%s: %s", ER_DEFAULT(ER_IPSOCK_ERROR), gai_strerror(error));
|
||||
unireg_abort(1); /* purecov: tested */
|
||||
if (real_bind_addr_str && *real_bind_addr_str)
|
||||
{
|
||||
|
||||
char *end;
|
||||
char address[FN_REFLEN];
|
||||
|
||||
do
|
||||
{
|
||||
end= strcend(real_bind_addr_str, ',');
|
||||
strmake(address, real_bind_addr_str, (uint) (end - real_bind_addr_str));
|
||||
|
||||
error= getaddrinfo(address, port_buf, &hints, &ai);
|
||||
if (unlikely(error != 0))
|
||||
{
|
||||
DBUG_PRINT("error", ("Got error: %d from getaddrinfo()", error));
|
||||
|
||||
sql_print_error("%s: %s", ER_DEFAULT(ER_IPSOCK_ERROR),
|
||||
gai_strerror(error));
|
||||
unireg_abort(1); /* purecov: tested */
|
||||
}
|
||||
|
||||
if (!head)
|
||||
{
|
||||
head= ai;
|
||||
}
|
||||
if (a)
|
||||
{
|
||||
a->ai_next= ai;
|
||||
}
|
||||
a= ai;
|
||||
while (a->ai_next)
|
||||
{
|
||||
a= a->ai_next;
|
||||
}
|
||||
|
||||
real_bind_addr_str= end + 1;
|
||||
} while (*end);
|
||||
}
|
||||
else
|
||||
{
|
||||
error= getaddrinfo(real_bind_addr_str, port_buf, &hints, &ai);
|
||||
head= ai;
|
||||
}
|
||||
|
||||
for (a= ai; a != NULL; a= a->ai_next)
|
||||
for (a= head; a != NULL; a= a->ai_next)
|
||||
{
|
||||
ip_sock= mysql_socket_socket(key_socket_tcpip, a->ai_family,
|
||||
a->ai_socktype, a->ai_protocol);
|
||||
@ -2410,9 +2445,31 @@ static void activate_tcp_port(uint port,
|
||||
if (ret < 0)
|
||||
{
|
||||
char buff[100];
|
||||
int s_errno= socket_errno;
|
||||
sprintf(buff, "Can't start server: Bind on TCP/IP port. Got error: %d",
|
||||
(int) socket_errno);
|
||||
(int) s_errno);
|
||||
sql_perror(buff);
|
||||
/*
|
||||
Linux will quite happily bind to addresses not present. The
|
||||
mtr test main.bind_multiple_addresses_resolution relies on this.
|
||||
For Windows, this is fatal and generates the error:
|
||||
WSAEADDRNOTAVAIL: The requested address is not valid in its context
|
||||
In this case, where multiple addresses where specified, maybe
|
||||
we can live with an error in the log and hope the other addresses
|
||||
are successful. We catch if no successful bindings occur at the
|
||||
end of this function.
|
||||
|
||||
FreeBSD returns EADDRNOTAVAIL, and EADDRNOTAVAIL is even in Linux
|
||||
manual pages. So may was well apply uniform behaviour.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
if (s_errno == WSAEADDRNOTAVAIL)
|
||||
continue;
|
||||
#endif
|
||||
#ifdef EADDRNOTAVAIL
|
||||
if (s_errno == EADDRNOTAVAIL)
|
||||
continue;
|
||||
#endif
|
||||
sql_print_error("Do you already have another server running on "
|
||||
"port: %u ?", port);
|
||||
unireg_abort(1);
|
||||
@ -2433,7 +2490,12 @@ static void activate_tcp_port(uint port,
|
||||
}
|
||||
}
|
||||
|
||||
freeaddrinfo(ai);
|
||||
freeaddrinfo(head);
|
||||
if (head && sockets->size() == 0)
|
||||
{
|
||||
sql_print_error("No TCP address could be bound to");
|
||||
unireg_abort(1);
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -511,7 +511,8 @@ static Sys_var_charptr_fscs Sys_basedir(
|
||||
DEFAULT(0));
|
||||
|
||||
static Sys_var_charptr_fscs Sys_my_bind_addr(
|
||||
"bind_address", "IP address to bind to.",
|
||||
"bind_address", "IP address to bind to. Several addresses may be "
|
||||
"specified, separated by a comma (,).",
|
||||
READ_ONLY GLOBAL_VAR(my_bind_addr_str), CMD_LINE(REQUIRED_ARG),
|
||||
DEFAULT(0));
|
||||
|
||||
|
@ -457,7 +457,13 @@ unsigned int wsrep_check_ip (const char* const addr, bool *is_ipv6)
|
||||
|
||||
*is_ipv6= false;
|
||||
|
||||
int gai_ret= getaddrinfo(addr, NULL, &hints, &res);
|
||||
char *end;
|
||||
char address[INET6_ADDRSTRLEN];
|
||||
|
||||
end= strcend(addr, ',');
|
||||
strmake(address, addr, (uint) (end - addr));
|
||||
|
||||
int gai_ret= getaddrinfo(address, NULL, &hints, &res);
|
||||
if (0 == gai_ret)
|
||||
{
|
||||
if (AF_INET == res->ai_family) /* IPv4 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user