MDEV-8034 : wsrep_node_address can't be IPV6
Updated address parsing logic to include IPv6 format.
This commit is contained in:
parent
31cf362c21
commit
bb52905432
@ -618,6 +618,7 @@ int wsrep_init()
|
|||||||
wsrep->provider_vendor, sizeof(provider_vendor) - 1);
|
wsrep->provider_vendor, sizeof(provider_vendor) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize node address */
|
||||||
char node_addr[512]= { 0, };
|
char node_addr[512]= { 0, };
|
||||||
size_t const node_addr_max= sizeof(node_addr) - 1;
|
size_t const node_addr_max= sizeof(node_addr) - 1;
|
||||||
if (!wsrep_node_address || !strcmp(wsrep_node_address, ""))
|
if (!wsrep_node_address || !strcmp(wsrep_node_address, ""))
|
||||||
@ -635,86 +636,81 @@ int wsrep_init()
|
|||||||
strncpy(node_addr, wsrep_node_address, node_addr_max);
|
strncpy(node_addr, wsrep_node_address, node_addr_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize node's incoming address */
|
||||||
char inc_addr[512]= { 0, };
|
char inc_addr[512]= { 0, };
|
||||||
size_t const inc_addr_max= sizeof (inc_addr);
|
size_t const inc_addr_max= sizeof (inc_addr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
In case wsrep_node_incoming_address is either not set or set to AUTO,
|
||||||
|
we need to use mysqld's my_bind_addr_str:mysqld_port, lastly fallback
|
||||||
|
to wsrep_node_address' value if mysqld's bind-address is not set either.
|
||||||
|
*/
|
||||||
if ((!wsrep_node_incoming_address ||
|
if ((!wsrep_node_incoming_address ||
|
||||||
!strcmp (wsrep_node_incoming_address, WSREP_NODE_INCOMING_AUTO)))
|
!strcmp (wsrep_node_incoming_address, WSREP_NODE_INCOMING_AUTO)))
|
||||||
{
|
{
|
||||||
|
bool is_ipv6= false;
|
||||||
unsigned int my_bind_ip= INADDR_ANY; // default if not set
|
unsigned int my_bind_ip= INADDR_ANY; // default if not set
|
||||||
|
|
||||||
if (my_bind_addr_str && strlen(my_bind_addr_str))
|
if (my_bind_addr_str && strlen(my_bind_addr_str))
|
||||||
{
|
{
|
||||||
my_bind_ip= wsrep_check_ip(my_bind_addr_str);
|
my_bind_ip= wsrep_check_ip(my_bind_addr_str, &is_ipv6);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (INADDR_ANY != my_bind_ip)
|
if (INADDR_ANY != my_bind_ip)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
If its a not a valid address, leave inc_addr as empty string. mysqld
|
||||||
|
is not listening for client connections on network interfaces.
|
||||||
|
*/
|
||||||
if (INADDR_NONE != my_bind_ip && INADDR_LOOPBACK != my_bind_ip)
|
if (INADDR_NONE != my_bind_ip && INADDR_LOOPBACK != my_bind_ip)
|
||||||
{
|
{
|
||||||
snprintf(inc_addr, inc_addr_max, "%s:%u",
|
const char *fmt= (is_ipv6) ? "[%s]:%u" : "%s:%u";
|
||||||
my_bind_addr_str, (int)mysqld_port);
|
snprintf(inc_addr, inc_addr_max, fmt, my_bind_addr_str, mysqld_port);
|
||||||
} // else leave inc_addr an empty string - mysqld is not listening for
|
}
|
||||||
// client connections on network interfaces.
|
|
||||||
}
|
}
|
||||||
else // mysqld binds to 0.0.0.0, take IP from wsrep_node_address if possible
|
else /* mysqld binds to 0.0.0.0, try taking IP from wsrep_node_address. */
|
||||||
{
|
{
|
||||||
size_t const node_addr_len= strlen(node_addr);
|
size_t const node_addr_len= strlen(node_addr);
|
||||||
if (node_addr_len > 0)
|
if (node_addr_len > 0)
|
||||||
{
|
{
|
||||||
const char* const colon= strrchr(node_addr, ':');
|
wsp::Address addr(node_addr);
|
||||||
if (strchr(node_addr, ':') == colon) // 1 or 0 ':'
|
|
||||||
{
|
|
||||||
size_t const ip_len= colon ? colon - node_addr : node_addr_len;
|
|
||||||
if (ip_len + 7 /* :55555\0 */ < inc_addr_max)
|
|
||||||
{
|
|
||||||
memcpy (inc_addr, node_addr, ip_len);
|
|
||||||
snprintf(inc_addr + ip_len, inc_addr_max - ip_len, ":%u",
|
|
||||||
(int)mysqld_port);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WSREP_WARN("Guessing address for incoming client connections: "
|
|
||||||
"address too long.");
|
|
||||||
inc_addr[0]= '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WSREP_WARN("Guessing address for incoming client connections: "
|
|
||||||
"too many colons :) .");
|
|
||||||
inc_addr[0]= '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strlen(inc_addr))
|
if (!addr.is_valid())
|
||||||
{
|
{
|
||||||
|
WSREP_DEBUG("Could not parse node address : %s", node_addr);
|
||||||
WSREP_WARN("Guessing address for incoming client connections failed. "
|
WSREP_WARN("Guessing address for incoming client connections failed. "
|
||||||
"Try setting wsrep_node_incoming_address explicitly.");
|
"Try setting wsrep_node_incoming_address explicitly.");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *fmt= (addr.is_ipv6()) ? "[%s]:%u" : "%s:%u";
|
||||||
|
snprintf(inc_addr, inc_addr_max, fmt, addr.get_address(),
|
||||||
|
(int) mysqld_port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strchr(wsrep_node_incoming_address, ':')) // no port included
|
|
||||||
{
|
|
||||||
if ((int)inc_addr_max <=
|
|
||||||
snprintf(inc_addr, inc_addr_max, "%s:%u",
|
|
||||||
wsrep_node_incoming_address,(int)mysqld_port))
|
|
||||||
{
|
|
||||||
WSREP_WARN("Guessing address for incoming client connections: "
|
|
||||||
"address too long.");
|
|
||||||
inc_addr[0]= '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size_t const need = strlen (wsrep_node_incoming_address);
|
wsp::Address addr(wsrep_node_incoming_address);
|
||||||
if (need >= inc_addr_max) {
|
|
||||||
WSREP_WARN("wsrep_node_incoming_address too long: %zu", need);
|
if (!addr.is_valid())
|
||||||
inc_addr[0]= '\0';
|
{
|
||||||
}
|
WSREP_WARN("Could not parse wsrep_node_incoming_address : %s",
|
||||||
else {
|
wsrep_node_incoming_address);
|
||||||
memcpy (inc_addr, wsrep_node_incoming_address, need);
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
In case port is not specified in wsrep_node_incoming_address, we use
|
||||||
|
mysqld_port.
|
||||||
|
*/
|
||||||
|
int port= (addr.get_port() > 0) ? addr.get_port() : (int) mysqld_port;
|
||||||
|
const char *fmt= (addr.is_ipv6()) ? "[%s]:%u" : "%s:%u";
|
||||||
|
|
||||||
|
snprintf(inc_addr, inc_addr_max, fmt, addr.get_address(), port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
struct wsrep_init_args wsrep_args;
|
struct wsrep_init_args wsrep_args;
|
||||||
|
|
||||||
struct wsrep_gtid const state_id = { local_uuid, local_seqno };
|
struct wsrep_gtid const state_id = { local_uuid, local_seqno };
|
||||||
|
@ -629,8 +629,6 @@ static bool SE_initialized = false;
|
|||||||
|
|
||||||
ssize_t wsrep_sst_prepare (void** msg)
|
ssize_t wsrep_sst_prepare (void** msg)
|
||||||
{
|
{
|
||||||
const ssize_t ip_max= 256;
|
|
||||||
char ip_buf[ip_max];
|
|
||||||
const char* addr_in= NULL;
|
const char* addr_in= NULL;
|
||||||
const char* addr_out= NULL;
|
const char* addr_out= NULL;
|
||||||
|
|
||||||
@ -646,27 +644,34 @@ ssize_t wsrep_sst_prepare (void** msg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Figure out SST address. Common for all SST methods
|
/*
|
||||||
|
Figure out SST receive address. Common for all SST methods.
|
||||||
|
*/
|
||||||
|
char ip_buf[256];
|
||||||
|
const ssize_t ip_max= sizeof(ip_buf);
|
||||||
|
|
||||||
|
// Attempt 1: wsrep_sst_receive_address
|
||||||
if (wsrep_sst_receive_address &&
|
if (wsrep_sst_receive_address &&
|
||||||
strcmp (wsrep_sst_receive_address, WSREP_SST_ADDRESS_AUTO))
|
strcmp (wsrep_sst_receive_address, WSREP_SST_ADDRESS_AUTO))
|
||||||
{
|
{
|
||||||
addr_in= wsrep_sst_receive_address;
|
addr_in= wsrep_sst_receive_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Attempt 2: wsrep_node_address
|
||||||
else if (wsrep_node_address && strlen(wsrep_node_address))
|
else if (wsrep_node_address && strlen(wsrep_node_address))
|
||||||
{
|
{
|
||||||
const char* const colon= strchr (wsrep_node_address, ':');
|
wsp::Address addr(wsrep_node_address);
|
||||||
if (colon)
|
|
||||||
|
if (!addr.is_valid())
|
||||||
{
|
{
|
||||||
ptrdiff_t const len= colon - wsrep_node_address;
|
WSREP_ERROR("Could not parse wsrep_node_address : %s",
|
||||||
strncpy (ip_buf, wsrep_node_address, len);
|
wsrep_node_address);
|
||||||
ip_buf[len]= '\0';
|
unireg_abort(1);
|
||||||
addr_in= ip_buf;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
addr_in= wsrep_node_address;
|
|
||||||
}
|
}
|
||||||
|
memcpy(ip_buf, addr.get_address(), addr.get_address_len());
|
||||||
|
addr_in= ip_buf;
|
||||||
}
|
}
|
||||||
|
// Attempt 3: Try to get the IP from the list of available interfaces.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ssize_t ret= wsrep_guess_ip (ip_buf, ip_max);
|
ssize_t ret= wsrep_guess_ip (ip_buf, ip_max);
|
||||||
@ -677,8 +682,7 @@ ssize_t wsrep_sst_prepare (void** msg)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WSREP_ERROR("Could not prepare state transfer request: "
|
WSREP_ERROR("Failed to guess address to accept state transfer. "
|
||||||
"failed to guess address to accept state transfer at. "
|
|
||||||
"wsrep_sst_receive_address must be set manually.");
|
"wsrep_sst_receive_address must be set manually.");
|
||||||
unireg_abort(1);
|
unireg_abort(1);
|
||||||
}
|
}
|
||||||
@ -778,8 +782,10 @@ static void sst_reject_queries(my_bool close_conn)
|
|||||||
if (TRUE == close_conn) wsrep_close_client_connections(FALSE);
|
if (TRUE == close_conn) wsrep_close_client_connections(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sst_mysqldump_check_addr (const char* user, const char* pswd,
|
static int sst_mysqldump_check_addr (const char* user,
|
||||||
const char* host, const char* port)
|
const char* pswd,
|
||||||
|
const char* host,
|
||||||
|
int port)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -790,25 +796,17 @@ static int sst_donate_mysqldump (const char* addr,
|
|||||||
wsrep_seqno_t seqno,
|
wsrep_seqno_t seqno,
|
||||||
bool bypass)
|
bool bypass)
|
||||||
{
|
{
|
||||||
size_t host_len;
|
char host[256];
|
||||||
const char* port = strchr (addr, ':');
|
wsp::Address address(addr);
|
||||||
|
|
||||||
if (port)
|
if (!address.is_valid())
|
||||||
{
|
{
|
||||||
port += 1;
|
WSREP_ERROR("Could not parse SST address : %s", addr);
|
||||||
host_len = port - addr;
|
return 0;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
port = "";
|
|
||||||
host_len = strlen (addr) + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *host= (char *) alloca(host_len);
|
memcpy(host, address.get_address(), address.get_address_len());
|
||||||
|
int port= address.get_port();
|
||||||
strncpy (host, addr, host_len - 1);
|
|
||||||
host[host_len - 1] = '\0';
|
|
||||||
|
|
||||||
const char* auth = sst_auth_real;
|
const char* auth = sst_auth_real;
|
||||||
const char* pswd = (auth) ? strchr (auth, ':') : NULL;
|
const char* pswd = (auth) ? strchr (auth, ':') : NULL;
|
||||||
size_t user_len;
|
size_t user_len;
|
||||||
@ -843,7 +841,7 @@ static int sst_donate_mysqldump (const char* addr,
|
|||||||
WSREP_SST_OPT_USER" '%s' "
|
WSREP_SST_OPT_USER" '%s' "
|
||||||
WSREP_SST_OPT_PSWD" '%s' "
|
WSREP_SST_OPT_PSWD" '%s' "
|
||||||
WSREP_SST_OPT_HOST" '%s' "
|
WSREP_SST_OPT_HOST" '%s' "
|
||||||
WSREP_SST_OPT_PORT" '%s' "
|
WSREP_SST_OPT_PORT" '%d' "
|
||||||
WSREP_SST_OPT_LPORT" '%u' "
|
WSREP_SST_OPT_LPORT" '%u' "
|
||||||
WSREP_SST_OPT_SOCKET" '%s' "
|
WSREP_SST_OPT_SOCKET" '%s' "
|
||||||
" %s "
|
" %s "
|
||||||
|
@ -352,7 +352,7 @@ thd::~thd ()
|
|||||||
} // namespace wsp
|
} // namespace wsp
|
||||||
|
|
||||||
/* Returns INADDR_NONE, INADDR_ANY, INADDR_LOOPBACK or something else */
|
/* Returns INADDR_NONE, INADDR_ANY, INADDR_LOOPBACK or something else */
|
||||||
unsigned int wsrep_check_ip (const char* const addr)
|
unsigned int wsrep_check_ip (const char* const addr, bool *is_ipv6)
|
||||||
{
|
{
|
||||||
unsigned int ret = INADDR_NONE;
|
unsigned int ret = INADDR_NONE;
|
||||||
struct addrinfo *res, hints;
|
struct addrinfo *res, hints;
|
||||||
@ -362,6 +362,8 @@ unsigned int wsrep_check_ip (const char* const addr)
|
|||||||
hints.ai_socktype= SOCK_STREAM;
|
hints.ai_socktype= SOCK_STREAM;
|
||||||
hints.ai_family= AF_UNSPEC;
|
hints.ai_family= AF_UNSPEC;
|
||||||
|
|
||||||
|
*is_ipv6= false;
|
||||||
|
|
||||||
int gai_ret = getaddrinfo(addr, NULL, &hints, &res);
|
int gai_ret = getaddrinfo(addr, NULL, &hints, &res);
|
||||||
if (0 == gai_ret)
|
if (0 == gai_ret)
|
||||||
{
|
{
|
||||||
@ -379,6 +381,8 @@ unsigned int wsrep_check_ip (const char* const addr)
|
|||||||
ret= INADDR_LOOPBACK;
|
ret= INADDR_LOOPBACK;
|
||||||
else
|
else
|
||||||
ret= 0xdeadbeef;
|
ret= 0xdeadbeef;
|
||||||
|
|
||||||
|
*is_ipv6= true;
|
||||||
}
|
}
|
||||||
freeaddrinfo (res);
|
freeaddrinfo (res);
|
||||||
}
|
}
|
||||||
@ -387,10 +391,6 @@ unsigned int wsrep_check_ip (const char* const addr)
|
|||||||
addr, gai_ret, gai_strerror(gai_ret));
|
addr, gai_ret, gai_strerror(gai_ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
// uint8_t* b= (uint8_t*)&ret;
|
|
||||||
// fprintf (stderr, "########## wsrep_check_ip returning: %hhu.%hhu.%hhu.%hhu\n",
|
|
||||||
// b[0], b[1], b[2], b[3]);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,44 +398,47 @@ extern char* my_bind_addr_str;
|
|||||||
|
|
||||||
size_t wsrep_guess_ip (char* buf, size_t buf_len)
|
size_t wsrep_guess_ip (char* buf, size_t buf_len)
|
||||||
{
|
{
|
||||||
size_t ip_len = 0;
|
size_t ret= 0;
|
||||||
|
|
||||||
|
// Attempt 1: Try to get the IP from bind-address.
|
||||||
if (my_bind_addr_str && my_bind_addr_str[0] != '\0')
|
if (my_bind_addr_str && my_bind_addr_str[0] != '\0')
|
||||||
{
|
{
|
||||||
unsigned int const ip_type= wsrep_check_ip(my_bind_addr_str);
|
bool unused;
|
||||||
|
unsigned int const ip_type= wsrep_check_ip(my_bind_addr_str, &unused);
|
||||||
|
|
||||||
if (INADDR_NONE == ip_type) {
|
if (INADDR_NONE == ip_type) {
|
||||||
WSREP_ERROR("Networking not configured, cannot receive state "
|
WSREP_ERROR("Networking not configured, cannot receive state "
|
||||||
"transfer.");
|
"transfer.");
|
||||||
return 0;
|
ret= 0;
|
||||||
}
|
} else if (INADDR_ANY != ip_type) {
|
||||||
|
|
||||||
if (INADDR_ANY != ip_type) {
|
|
||||||
strncpy (buf, my_bind_addr_str, buf_len);
|
strncpy (buf, my_bind_addr_str, buf_len);
|
||||||
return strlen(buf);
|
ret= strlen(buf);
|
||||||
}
|
}
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mysqld binds to all interfaces - try IP from wsrep_node_address
|
// Attempt 2: mysqld binds to all interfaces, try IP from wsrep_node_address.
|
||||||
if (wsrep_node_address && wsrep_node_address[0] != '\0') {
|
if (wsrep_node_address && wsrep_node_address[0] != '\0') {
|
||||||
const char* const colon_ptr = strchr(wsrep_node_address, ':');
|
wsp::Address addr(wsrep_node_address);
|
||||||
|
if (!addr.is_valid())
|
||||||
if (colon_ptr)
|
{
|
||||||
ip_len = colon_ptr - wsrep_node_address;
|
WSREP_WARN("Could not parse wsrep_node_address : %s",
|
||||||
else
|
wsrep_node_address);
|
||||||
ip_len = strlen(wsrep_node_address);
|
ret= 0;
|
||||||
|
goto done;
|
||||||
if (ip_len >= buf_len) {
|
|
||||||
WSREP_WARN("default_ip(): buffer too short: %zu <= %zd", buf_len, ip_len);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy (buf, wsrep_node_address, ip_len);
|
/* Safety check: Buffer length should be sufficiently large. */
|
||||||
buf[ip_len] = '\0';
|
DBUG_ASSERT(buf_len >= addr.get_address_len());
|
||||||
return ip_len;
|
|
||||||
|
memcpy(buf, addr.get_address(), addr.get_address_len());
|
||||||
|
ret= addr.get_address_len();
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Attempt 3: Try to get the IP from the list of available interfaces.
|
||||||
|
|
||||||
getifaddrs() is avaiable at least on Linux since glib 2.3, FreeBSD,
|
getifaddrs() is avaiable at least on Linux since glib 2.3, FreeBSD,
|
||||||
MAC OSX, OpenSolaris, Solaris.
|
MAC OSX, OpenSolaris, Solaris.
|
||||||
|
|
||||||
@ -444,26 +447,42 @@ size_t wsrep_guess_ip (char* buf, size_t buf_len)
|
|||||||
*/
|
*/
|
||||||
#if HAVE_GETIFADDRS
|
#if HAVE_GETIFADDRS
|
||||||
struct ifaddrs *ifaddr, *ifa;
|
struct ifaddrs *ifaddr, *ifa;
|
||||||
|
int family;
|
||||||
|
|
||||||
if (getifaddrs(&ifaddr) == 0)
|
if (getifaddrs(&ifaddr) == 0)
|
||||||
{
|
{
|
||||||
for (ifa= ifaddr; ifa != NULL; ifa = ifa->ifa_next)
|
for (ifa= ifaddr; ifa != NULL; ifa = ifa->ifa_next)
|
||||||
{
|
{
|
||||||
if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET) // TODO AF_INET6
|
if (!ifa->ifa_addr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
family= ifa->ifa_addr->sa_family;
|
||||||
|
|
||||||
|
if ((family != AF_INET) && (family != AF_INET6))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Skip loopback interfaces (like lo:127.0.0.1)
|
// Skip loopback interfaces (like lo:127.0.0.1)
|
||||||
if (ifa->ifa_flags & IFF_LOOPBACK)
|
if (ifa->ifa_flags & IFF_LOOPBACK)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get IP address from the socket address. The resulting address may have
|
||||||
|
zone ID appended for IPv6 addresses (<address>%<zone-id>).
|
||||||
|
*/
|
||||||
if (vio_getnameinfo(ifa->ifa_addr, buf, buf_len, NULL, 0, NI_NUMERICHOST))
|
if (vio_getnameinfo(ifa->ifa_addr, buf, buf_len, NULL, 0, NI_NUMERICHOST))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
freeifaddrs(ifaddr);
|
freeifaddrs(ifaddr);
|
||||||
return strlen(buf);
|
|
||||||
|
ret= strlen(buf);
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
freeifaddrs(ifaddr);
|
freeifaddrs(ifaddr);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_GETIFADDRS */
|
#endif /* HAVE_GETIFADDRS */
|
||||||
|
|
||||||
return 0;
|
done:
|
||||||
|
WSREP_DEBUG("wsrep_guess_ip() : %s", (ret > 0) ? buf : "????");
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,11 +19,153 @@
|
|||||||
#include "wsrep_priv.h"
|
#include "wsrep_priv.h"
|
||||||
#include "wsrep_mysqld.h"
|
#include "wsrep_mysqld.h"
|
||||||
|
|
||||||
unsigned int wsrep_check_ip (const char* addr);
|
unsigned int wsrep_check_ip (const char* addr, bool *is_ipv6);
|
||||||
size_t wsrep_guess_ip (char* buf, size_t buf_len);
|
size_t wsrep_guess_ip (char* buf, size_t buf_len);
|
||||||
|
|
||||||
namespace wsp {
|
namespace wsp {
|
||||||
|
|
||||||
|
class Address {
|
||||||
|
public:
|
||||||
|
Address()
|
||||||
|
: m_address_len(0), m_family(UNSPEC), m_port(0), m_valid(false)
|
||||||
|
{
|
||||||
|
memset(m_address, 0, sizeof(m_address));
|
||||||
|
}
|
||||||
|
Address(const char *addr_in)
|
||||||
|
: m_address_len(0), m_family(UNSPEC), m_port(0), m_valid(false)
|
||||||
|
{
|
||||||
|
memset(m_address, 0, sizeof(m_address));
|
||||||
|
parse_addr(addr_in);
|
||||||
|
}
|
||||||
|
bool is_valid() { return m_valid; }
|
||||||
|
bool is_ipv6() { return (m_family == INET6); }
|
||||||
|
|
||||||
|
const char* get_address() { return m_address; }
|
||||||
|
size_t get_address_len() { return m_address_len; }
|
||||||
|
int get_port() { return m_port; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum family {
|
||||||
|
UNSPEC= 0,
|
||||||
|
INET, /* IPv4 */
|
||||||
|
INET6, /* IPv6 */
|
||||||
|
};
|
||||||
|
|
||||||
|
char m_address[256];
|
||||||
|
size_t m_address_len;
|
||||||
|
family m_family;
|
||||||
|
int m_port;
|
||||||
|
bool m_valid;
|
||||||
|
|
||||||
|
void parse_addr(const char *addr_in) {
|
||||||
|
const char *start;
|
||||||
|
const char *end;
|
||||||
|
const char *port;
|
||||||
|
const char* open_bracket= strchr(const_cast<char *>(addr_in), '[');
|
||||||
|
const char* close_bracket= strchr(const_cast<char *>(addr_in), ']');
|
||||||
|
const char* colon= strchr(const_cast<char *>(addr_in), ':');
|
||||||
|
const char* dot= strchr(const_cast<char *>(addr_in), '.');
|
||||||
|
|
||||||
|
int cc= colon_count(addr_in);
|
||||||
|
|
||||||
|
if (open_bracket != NULL ||
|
||||||
|
dot == NULL ||
|
||||||
|
(colon != NULL && (dot == NULL || colon < dot)))
|
||||||
|
{
|
||||||
|
// This could be an IPv6 address or a hostname
|
||||||
|
if (open_bracket != NULL) {
|
||||||
|
/* Sanity check: Address with '[' must include ']' */
|
||||||
|
if (close_bracket == NULL &&
|
||||||
|
open_bracket < close_bracket) /* Error: malformed address */
|
||||||
|
{
|
||||||
|
m_valid= false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
start= open_bracket + 1;
|
||||||
|
end= close_bracket;
|
||||||
|
|
||||||
|
/* Check for port */
|
||||||
|
port= strchr(close_bracket, ':');
|
||||||
|
if ((port != NULL) && parse_port(port + 1))
|
||||||
|
{
|
||||||
|
return; /* Error: invalid port */
|
||||||
|
}
|
||||||
|
m_family= INET6;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (cc) {
|
||||||
|
case 0:
|
||||||
|
/* Hostname with no port */
|
||||||
|
start= addr_in;
|
||||||
|
end= addr_in + strlen(addr_in);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
/* Hostname with port (host:port) */
|
||||||
|
start= addr_in;
|
||||||
|
end= colon;
|
||||||
|
parse_port(colon + 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* IPv6 address */
|
||||||
|
start= addr_in;
|
||||||
|
end= addr_in + strlen(addr_in);
|
||||||
|
m_family= INET6;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { /* IPv4 address or hostname */
|
||||||
|
start= addr_in;
|
||||||
|
if (colon != NULL) { /* Port */
|
||||||
|
end= colon;
|
||||||
|
if (parse_port(colon + 1))
|
||||||
|
return; /* Error: invalid port */
|
||||||
|
} else {
|
||||||
|
end= addr_in + strlen(addr_in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t len= end - start;
|
||||||
|
|
||||||
|
/* Safety */
|
||||||
|
if (len >= sizeof(m_address))
|
||||||
|
{
|
||||||
|
// The supplied address is too large to fit into the internal buffer.
|
||||||
|
m_valid= false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(m_address, start, len);
|
||||||
|
m_address[len]= '\0';
|
||||||
|
m_address_len= ++ len;
|
||||||
|
m_valid= true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int colon_count(const char *addr) {
|
||||||
|
int count= 0, i= 0;
|
||||||
|
|
||||||
|
while(addr[i] != '\0')
|
||||||
|
{
|
||||||
|
if (addr[i] == ':') ++count;
|
||||||
|
++ i;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parse_port(const char *port) {
|
||||||
|
m_port= strtol(port, NULL, 10);
|
||||||
|
if (errno == EINVAL || errno == ERANGE)
|
||||||
|
{
|
||||||
|
m_port= 0; /* Error: invalid port */
|
||||||
|
m_valid= false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class Config_state
|
class Config_state
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user