Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
bb529054
Commit
bb529054
authored
Sep 15, 2015
by
Nirbhay Choubey
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-8034 : wsrep_node_address can't be IPV6
Updated address parsing logic to include IPv6 format.
parent
31cf362c
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
268 additions
and
113 deletions
+268
-113
sql/wsrep_mysqld.cc
sql/wsrep_mysqld.cc
+46
-50
sql/wsrep_sst.cc
sql/wsrep_sst.cc
+31
-33
sql/wsrep_utils.cc
sql/wsrep_utils.cc
+48
-29
sql/wsrep_utils.h
sql/wsrep_utils.h
+143
-1
No files found.
sql/wsrep_mysqld.cc
View file @
bb529054
...
...
@@ -618,6 +618,7 @@ int wsrep_init()
wsrep
->
provider_vendor
,
sizeof
(
provider_vendor
)
-
1
);
}
/* Initialize node address */
char
node_addr
[
512
]
=
{
0
,
};
size_t
const
node_addr_max
=
sizeof
(
node_addr
)
-
1
;
if
(
!
wsrep_node_address
||
!
strcmp
(
wsrep_node_address
,
""
))
...
...
@@ -635,86 +636,81 @@ int wsrep_init()
strncpy
(
node_addr
,
wsrep_node_address
,
node_addr_max
);
}
/* Initialize node's incoming address */
char
inc_addr
[
512
]
=
{
0
,
};
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
||
!
strcmp
(
wsrep_node_incoming_address
,
WSREP_NODE_INCOMING_AUTO
)))
{
bool
is_ipv6
=
false
;
unsigned
int
my_bind_ip
=
INADDR_ANY
;
// default if not set
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 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
)
{
snprintf
(
inc_addr
,
inc_addr_max
,
"%s:%u"
,
my_bind_addr_str
,
(
int
)
mysqld_port
);
}
// else leave inc_addr an empty string - mysqld is not listening for
// client connections on network interfaces.
const
char
*
fmt
=
(
is_ipv6
)
?
"[%s]:%u"
:
"%s:%u"
;
snprintf
(
inc_addr
,
inc_addr_max
,
fmt
,
my_bind_addr_str
,
mysqld_port
);
}
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
);
if
(
node_addr_len
>
0
)
{
const
char
*
const
colon
=
strrchr
(
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'
;
}
}
wsp
::
Address
addr
(
node_addr
);
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. "
"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
{
size_t
const
need
=
strlen
(
wsrep_node_incoming_address
);
if
(
need
>=
inc_addr_max
)
{
WSREP_WARN
(
"wsrep_node_incoming_address too long: %zu"
,
need
);
inc_addr
[
0
]
=
'\0'
;
}
else
{
memcpy
(
inc_addr
,
wsrep_node_incoming_address
,
need
)
;
wsp
::
Address
addr
(
wsrep_node_incoming_address
);
if
(
!
addr
.
is_valid
())
{
WSREP_WARN
(
"Could not parse wsrep_node_incoming_address : %s"
,
wsrep_node_incoming_address
);
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_gtid
const
state_id
=
{
local_uuid
,
local_seqno
};
...
...
sql/wsrep_sst.cc
View file @
bb529054
...
...
@@ -629,8 +629,6 @@ static bool SE_initialized = false;
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_out
=
NULL
;
...
...
@@ -646,27 +644,34 @@ ssize_t wsrep_sst_prepare (void** msg)
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
&&
strcmp
(
wsrep_sst_receive_address
,
WSREP_SST_ADDRESS_AUTO
))
{
addr_in
=
wsrep_sst_receive_address
;
}
//Attempt 2: wsrep_node_address
else
if
(
wsrep_node_address
&&
strlen
(
wsrep_node_address
))
{
const
char
*
const
colon
=
strchr
(
wsrep_node_address
,
':'
);
if
(
colon
)
{
ptrdiff_t
const
len
=
colon
-
wsrep_node_address
;
strncpy
(
ip_buf
,
wsrep_node_address
,
len
);
ip_buf
[
len
]
=
'\0'
;
addr_in
=
ip_buf
;
}
else
wsp
::
Address
addr
(
wsrep_node_address
);
if
(
!
addr
.
is_valid
())
{
addr_in
=
wsrep_node_address
;
WSREP_ERROR
(
"Could not parse wsrep_node_address : %s"
,
wsrep_node_address
);
unireg_abort
(
1
);
}
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
{
ssize_t
ret
=
wsrep_guess_ip
(
ip_buf
,
ip_max
);
...
...
@@ -677,8 +682,7 @@ ssize_t wsrep_sst_prepare (void** msg)
}
else
{
WSREP_ERROR
(
"Could not prepare state transfer request: "
"failed to guess address to accept state transfer at. "
WSREP_ERROR
(
"Failed to guess address to accept state transfer. "
"wsrep_sst_receive_address must be set manually."
);
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
);
}
static
int
sst_mysqldump_check_addr
(
const
char
*
user
,
const
char
*
pswd
,
const
char
*
host
,
const
char
*
port
)
static
int
sst_mysqldump_check_addr
(
const
char
*
user
,
const
char
*
pswd
,
const
char
*
host
,
int
port
)
{
return
0
;
}
...
...
@@ -790,25 +796,17 @@ static int sst_donate_mysqldump (const char* addr,
wsrep_seqno_t
seqno
,
bool
bypass
)
{
size_t
host_len
;
const
char
*
port
=
strchr
(
addr
,
':'
);
char
host
[
256
]
;
wsp
::
Address
address
(
addr
);
if
(
port
)
{
port
+=
1
;
host_len
=
port
-
addr
;
}
else
if
(
!
address
.
is_valid
())
{
port
=
""
;
host_len
=
strlen
(
addr
)
+
1
;
WSREP_ERROR
(
"Could not parse SST address : %s"
,
addr
)
;
return
0
;
}
char
*
host
=
(
char
*
)
alloca
(
host_len
);
strncpy
(
host
,
addr
,
host_len
-
1
);
host
[
host_len
-
1
]
=
'\0'
;
memcpy
(
host
,
address
.
get_address
(),
address
.
get_address_len
());
int
port
=
address
.
get_port
();
const
char
*
auth
=
sst_auth_real
;
const
char
*
pswd
=
(
auth
)
?
strchr
(
auth
,
':'
)
:
NULL
;
size_t
user_len
;
...
...
@@ -843,7 +841,7 @@ static int sst_donate_mysqldump (const char* addr,
WSREP_SST_OPT_USER
" '%s' "
WSREP_SST_OPT_PSWD
" '%s' "
WSREP_SST_OPT_HOST
" '%s' "
WSREP_SST_OPT_PORT
" '%
s
' "
WSREP_SST_OPT_PORT
" '%
d
' "
WSREP_SST_OPT_LPORT
" '%u' "
WSREP_SST_OPT_SOCKET
" '%s' "
" %s "
...
...
sql/wsrep_utils.cc
View file @
bb529054
...
...
@@ -352,7 +352,7 @@ thd::~thd ()
}
// namespace wsp
/* 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
;
struct
addrinfo
*
res
,
hints
;
...
...
@@ -362,6 +362,8 @@ unsigned int wsrep_check_ip (const char* const addr)
hints
.
ai_socktype
=
SOCK_STREAM
;
hints
.
ai_family
=
AF_UNSPEC
;
*
is_ipv6
=
false
;
int
gai_ret
=
getaddrinfo
(
addr
,
NULL
,
&
hints
,
&
res
);
if
(
0
==
gai_ret
)
{
...
...
@@ -379,6 +381,8 @@ unsigned int wsrep_check_ip (const char* const addr)
ret
=
INADDR_LOOPBACK
;
else
ret
=
0xdeadbeef
;
*
is_ipv6
=
true
;
}
freeaddrinfo
(
res
);
}
...
...
@@ -387,10 +391,6 @@ unsigned int wsrep_check_ip (const char* const addr)
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
;
}
...
...
@@ -398,44 +398,47 @@ extern char* my_bind_addr_str;
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'
)
{
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
)
{
WSREP_ERROR
(
"Networking not configured, cannot receive state "
"transfer."
);
return
0
;
}
if
(
INADDR_ANY
!=
ip_type
)
{
ret
=
0
;
}
else
if
(
INADDR_ANY
!=
ip_type
)
{
strncpy
(
buf
,
my_bind_addr_str
,
buf_len
);
ret
urn
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'
)
{
const
char
*
const
colon_ptr
=
strchr
(
wsrep_node_address
,
':'
);
if
(
colon_ptr
)
ip_len
=
colon_ptr
-
wsrep_node_address
;
else
ip_len
=
strlen
(
wsrep_node_address
);
if
(
ip_len
>=
buf_len
)
{
WSREP_WARN
(
"default_ip(): buffer too short: %zu <= %zd"
,
buf_len
,
ip_len
);
return
0
;
wsp
::
Address
addr
(
wsrep_node_address
);
if
(
!
addr
.
is_valid
())
{
WSREP_WARN
(
"Could not parse wsrep_node_address : %s"
,
wsrep_node_address
);
ret
=
0
;
goto
done
;
}
memcpy
(
buf
,
wsrep_node_address
,
ip_len
);
buf
[
ip_len
]
=
'\0'
;
return
ip_len
;
/* Safety check: Buffer length should be sufficiently large. */
DBUG_ASSERT
(
buf_len
>=
addr
.
get_address_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,
MAC OSX, OpenSolaris, Solaris.
...
...
@@ -444,26 +447,42 @@ size_t wsrep_guess_ip (char* buf, size_t buf_len)
*/
#if HAVE_GETIFADDRS
struct
ifaddrs
*
ifaddr
,
*
ifa
;
int
family
;
if
(
getifaddrs
(
&
ifaddr
)
==
0
)
{
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
;
// Skip loopback interfaces (like lo:127.0.0.1)
if
(
ifa
->
ifa_flags
&
IFF_LOOPBACK
)
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
))
continue
;
freeifaddrs
(
ifaddr
);
return
strlen
(
buf
);
ret
=
strlen
(
buf
);
goto
done
;
}
freeifaddrs
(
ifaddr
);
}
#endif
/* HAVE_GETIFADDRS */
return
0
;
done:
WSREP_DEBUG
(
"wsrep_guess_ip() : %s"
,
(
ret
>
0
)
?
buf
:
"????"
);
return
ret
;
}
sql/wsrep_utils.h
View file @
bb529054
...
...
@@ -19,11 +19,153 @@
#include "wsrep_priv.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
);
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
{
public:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment