ndb - bug#22195

  allow bind address for ndbd
parent 7ff631e8
...@@ -231,7 +231,9 @@ extern "C" { ...@@ -231,7 +231,9 @@ extern "C" {
NDB_MGM_SERVER_NOT_CONNECTED = 1010, NDB_MGM_SERVER_NOT_CONNECTED = 1010,
/** Could not connect to socker */ /** Could not connect to socker */
NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET = 1011, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET = 1011,
/** Could not bind local address */
NDB_MGM_BIND_ADDRESS = 1012,
/* Alloc node id failures */ /* Alloc node id failures */
/** Generic error, retry may succeed */ /** Generic error, retry may succeed */
NDB_MGM_ALLOCID_ERROR = 1101, NDB_MGM_ALLOCID_ERROR = 1101,
...@@ -515,6 +517,15 @@ extern "C" { ...@@ -515,6 +517,15 @@ extern "C" {
const char *ndb_mgm_get_connected_host(NdbMgmHandle handle); const char *ndb_mgm_get_connected_host(NdbMgmHandle handle);
const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz); const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz);
/**
* Set local bindaddress
* @param arg - Srting of form "host[:port]"
* @note must be called before connect
* @note Error on binding local address will not be reported until connect
* @return 0 on success
*/
int ndb_mgm_set_bindaddress(NdbMgmHandle, const char * arg);
/** /**
* Gets the connectstring used for a connection * Gets the connectstring used for a connection
* *
......
...@@ -28,7 +28,8 @@ ...@@ -28,7 +28,8 @@
class ConfigRetriever { class ConfigRetriever {
public: public:
ConfigRetriever(const char * _connect_string, ConfigRetriever(const char * _connect_string,
Uint32 version, Uint32 nodeType); Uint32 version, Uint32 nodeType,
const char * _bind_address = 0);
~ConfigRetriever(); ~ConfigRetriever();
int do_connect(int no_retries, int retry_delay_in_seconds, int verbose); int do_connect(int no_retries, int retry_delay_in_seconds, int verbose);
......
...@@ -37,7 +37,8 @@ public: ...@@ -37,7 +37,8 @@ public:
}; };
unsigned short get_port() { return m_port; }; unsigned short get_port() { return m_port; };
char *get_server_name() { return m_server_name; }; char *get_server_name() { return m_server_name; };
NDB_SOCKET_TYPE connect(); int bind(const char* toaddress, unsigned short toport);
NDB_SOCKET_TYPE connect(const char* toaddress = 0, unsigned short port = 0);
bool close(); bool close();
}; };
......
...@@ -45,7 +45,8 @@ ...@@ -45,7 +45,8 @@
//**************************************************************************** //****************************************************************************
ConfigRetriever::ConfigRetriever(const char * _connect_string, ConfigRetriever::ConfigRetriever(const char * _connect_string,
Uint32 version, Uint32 node_type) Uint32 version, Uint32 node_type,
const char * _bindaddress)
{ {
DBUG_ENTER("ConfigRetriever::ConfigRetriever"); DBUG_ENTER("ConfigRetriever::ConfigRetriever");
...@@ -66,6 +67,15 @@ ConfigRetriever::ConfigRetriever(const char * _connect_string, ...@@ -66,6 +67,15 @@ ConfigRetriever::ConfigRetriever(const char * _connect_string,
setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle)); setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
if (_bindaddress)
{
if (ndb_mgm_set_bindaddress(m_handle, _bindaddress))
{
setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
DBUG_VOID_RETURN;
}
}
resetError(); resetError();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -25,7 +25,7 @@ SocketClient::SocketClient(const char *server_name, unsigned short port, SocketA ...@@ -25,7 +25,7 @@ SocketClient::SocketClient(const char *server_name, unsigned short port, SocketA
{ {
m_auth= sa; m_auth= sa;
m_port= port; m_port= port;
m_server_name= strdup(server_name); m_server_name= server_name ? strdup(server_name) : 0;
m_sockfd= NDB_INVALID_SOCKET; m_sockfd= NDB_INVALID_SOCKET;
} }
...@@ -45,13 +45,16 @@ SocketClient::init() ...@@ -45,13 +45,16 @@ SocketClient::init()
if (m_sockfd != NDB_INVALID_SOCKET) if (m_sockfd != NDB_INVALID_SOCKET)
NDB_CLOSE_SOCKET(m_sockfd); NDB_CLOSE_SOCKET(m_sockfd);
memset(&m_servaddr, 0, sizeof(m_servaddr)); if (m_server_name)
m_servaddr.sin_family = AF_INET; {
m_servaddr.sin_port = htons(m_port); memset(&m_servaddr, 0, sizeof(m_servaddr));
// Convert ip address presentation format to numeric format m_servaddr.sin_family = AF_INET;
if (Ndb_getInAddr(&m_servaddr.sin_addr, m_server_name)) m_servaddr.sin_port = htons(m_port);
return false; // Convert ip address presentation format to numeric format
if (Ndb_getInAddr(&m_servaddr.sin_addr, m_server_name))
return false;
}
m_sockfd= socket(AF_INET, SOCK_STREAM, 0); m_sockfd= socket(AF_INET, SOCK_STREAM, 0);
if (m_sockfd == NDB_INVALID_SOCKET) { if (m_sockfd == NDB_INVALID_SOCKET) {
return false; return false;
...@@ -62,8 +65,45 @@ SocketClient::init() ...@@ -62,8 +65,45 @@ SocketClient::init()
return true; return true;
} }
int
SocketClient::bind(const char* bindaddress, unsigned short localport)
{
if (m_sockfd == NDB_INVALID_SOCKET)
return -1;
struct sockaddr_in local;
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
local.sin_port = htons(localport);
// Convert ip address presentation format to numeric format
if (Ndb_getInAddr(&local.sin_addr, bindaddress))
{
return errno ? errno : EINVAL;
}
const int on = 1;
if (setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR,
(const char*)&on, sizeof(on)) == -1) {
int ret = errno;
NDB_CLOSE_SOCKET(m_sockfd);
m_sockfd= NDB_INVALID_SOCKET;
return errno;
}
if (::bind(m_sockfd, (struct sockaddr*)&local, sizeof(local)) == -1)
{
int ret = errno;
NDB_CLOSE_SOCKET(m_sockfd);
m_sockfd= NDB_INVALID_SOCKET;
return ret;
}
return 0;
}
NDB_SOCKET_TYPE NDB_SOCKET_TYPE
SocketClient::connect() SocketClient::connect(const char *toaddress, unsigned short toport)
{ {
if (m_sockfd == NDB_INVALID_SOCKET) if (m_sockfd == NDB_INVALID_SOCKET)
{ {
...@@ -74,6 +114,21 @@ SocketClient::connect() ...@@ -74,6 +114,21 @@ SocketClient::connect()
return NDB_INVALID_SOCKET; return NDB_INVALID_SOCKET;
} }
} }
if (toaddress)
{
if (m_server_name)
free(m_server_name);
m_server_name = strdup(toaddress);
m_port = toport;
memset(&m_servaddr, 0, sizeof(m_servaddr));
m_servaddr.sin_family = AF_INET;
m_servaddr.sin_port = htons(toport);
// Convert ip address presentation format to numeric format
if (Ndb_getInAddr(&m_servaddr.sin_addr, m_server_name))
return NDB_INVALID_SOCKET;
}
const int r = ::connect(m_sockfd, (struct sockaddr*) &m_servaddr, sizeof(m_servaddr)); const int r = ::connect(m_sockfd, (struct sockaddr*) &m_servaddr, sizeof(m_servaddr));
if (r == -1) { if (r == -1) {
NDB_CLOSE_SOCKET(m_sockfd); NDB_CLOSE_SOCKET(m_sockfd);
......
...@@ -58,7 +58,8 @@ NDB_STD_OPTS_VARS; ...@@ -58,7 +58,8 @@ NDB_STD_OPTS_VARS;
// XXX should be my_bool ??? // XXX should be my_bool ???
static int _daemon, _no_daemon, _foreground, _initial, _no_start; static int _daemon, _no_daemon, _foreground, _initial, _no_start;
static int _initialstart; static int _initialstart;
static const char* _nowait_nodes; static const char* _nowait_nodes = 0;
static const char* _bind_address = 0;
extern Uint32 g_start_type; extern Uint32 g_start_type;
extern NdbNodeBitmask g_nowait_nodes; extern NdbNodeBitmask g_nowait_nodes;
...@@ -98,6 +99,10 @@ static struct my_option my_long_options[] = ...@@ -98,6 +99,10 @@ static struct my_option my_long_options[] =
"Perform initial start", "Perform initial start",
(gptr*) &_initialstart, (gptr*) &_initialstart, 0, (gptr*) &_initialstart, (gptr*) &_initialstart, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
{ "bind-address", OPT_NOWAIT_NODES,
"Local bind address",
(gptr*) &_bind_address, (gptr*) &_bind_address, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
}; };
static void short_usage_sub(void) static void short_usage_sub(void)
...@@ -257,7 +262,9 @@ Configuration::fetch_configuration(){ ...@@ -257,7 +262,9 @@ Configuration::fetch_configuration(){
m_mgmd_port= 0; m_mgmd_port= 0;
m_config_retriever= new ConfigRetriever(getConnectString(), m_config_retriever= new ConfigRetriever(getConnectString(),
NDB_VERSION, NODE_TYPE_DB); NDB_VERSION,
NODE_TYPE_DB,
_bind_address);
if (m_config_retriever->hasError()) if (m_config_retriever->hasError())
{ {
......
...@@ -107,6 +107,7 @@ struct ndb_mgm_handle { ...@@ -107,6 +107,7 @@ struct ndb_mgm_handle {
int mgmd_version_major; int mgmd_version_major;
int mgmd_version_minor; int mgmd_version_minor;
int mgmd_version_build; int mgmd_version_build;
char * m_bindaddress;
}; };
#define SET_ERROR(h, e, s) setError(h, e, __LINE__, s) #define SET_ERROR(h, e, s) setError(h, e, __LINE__, s)
...@@ -162,6 +163,7 @@ ndb_mgm_create_handle() ...@@ -162,6 +163,7 @@ ndb_mgm_create_handle()
h->cfg_i = -1; h->cfg_i = -1;
h->errstream = stdout; h->errstream = stdout;
h->m_name = 0; h->m_name = 0;
h->m_bindaddress = 0;
strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE); strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE);
...@@ -209,6 +211,22 @@ ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv) ...@@ -209,6 +211,22 @@ ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
extern "C"
int
ndb_mgm_set_bindaddress(NdbMgmHandle handle, const char * arg)
{
DBUG_ENTER("ndb_mgm_set_bindaddress");
if (handle->m_bindaddress)
free(handle->m_bindaddress);
if (arg)
handle->m_bindaddress = strdup(arg);
else
handle->m_bindaddress = 0;
DBUG_RETURN(0);
}
/** /**
* Destroy a handle * Destroy a handle
*/ */
...@@ -235,6 +253,8 @@ ndb_mgm_destroy_handle(NdbMgmHandle * handle) ...@@ -235,6 +253,8 @@ ndb_mgm_destroy_handle(NdbMgmHandle * handle)
#endif #endif
(*handle)->cfg.~LocalConfig(); (*handle)->cfg.~LocalConfig();
my_free((*handle)->m_name, MYF(MY_ALLOW_ZERO_PTR)); my_free((*handle)->m_name, MYF(MY_ALLOW_ZERO_PTR));
if ((*handle)->m_bindaddress)
free((*handle)->m_bindaddress);
my_free((char*)* handle,MYF(MY_ALLOW_ZERO_PTR)); my_free((char*)* handle,MYF(MY_ALLOW_ZERO_PTR));
* handle = 0; * handle = 0;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -427,6 +447,7 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries, ...@@ -427,6 +447,7 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
BaseString::snprintf(logname, 64, "mgmapi.log"); BaseString::snprintf(logname, 64, "mgmapi.log");
handle->logfile = fopen(logname, "w"); handle->logfile = fopen(logname, "w");
#endif #endif
char buf[1024];
/** /**
* Do connect * Do connect
...@@ -434,6 +455,50 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries, ...@@ -434,6 +455,50 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
LocalConfig &cfg= handle->cfg; LocalConfig &cfg= handle->cfg;
NDB_SOCKET_TYPE sockfd= NDB_INVALID_SOCKET; NDB_SOCKET_TYPE sockfd= NDB_INVALID_SOCKET;
Uint32 i; Uint32 i;
int binderror = 0;
SocketClient s(0, 0);
if (!s.init())
{
fprintf(handle->errstream,
"Unable to create socket, "
"while trying to connect with connect string: %s\n",
cfg.makeConnectString(buf,sizeof(buf)));
setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
"Unable to create socket, "
"while trying to connect with connect string: %s\n",
cfg.makeConnectString(buf,sizeof(buf)));
DBUG_RETURN(-1);
}
if (handle->m_bindaddress)
{
BaseString::snprintf(buf, sizeof(buf), handle->m_bindaddress);
unsigned short portno = 0;
char * port = strchr(buf, ':');
if (port != 0)
{
portno = atoi(port+1);
* port = 0;
}
int err;
if ((err = s.bind(buf, portno)) != 0)
{
fprintf(handle->errstream,
"Unable to bind local address %s errno: %d, "
"while trying to connect with connect string: %s\n",
handle->m_bindaddress, err,
cfg.makeConnectString(buf,sizeof(buf)));
setError(handle, NDB_MGM_BIND_ADDRESS, __LINE__,
"Unable to bind local address %s errno: %d, "
"while trying to connect with connect string: %s\n",
handle->m_bindaddress, err,
cfg.makeConnectString(buf,sizeof(buf)));
DBUG_RETURN(-1);
}
}
while (sockfd == NDB_INVALID_SOCKET) while (sockfd == NDB_INVALID_SOCKET)
{ {
// do all the mgmt servers // do all the mgmt servers
...@@ -441,8 +506,7 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries, ...@@ -441,8 +506,7 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
{ {
if (cfg.ids[i].type != MgmId_TCP) if (cfg.ids[i].type != MgmId_TCP)
continue; continue;
SocketClient s(cfg.ids[i].name.c_str(), cfg.ids[i].port); sockfd = s.connect(cfg.ids[i].name.c_str(), cfg.ids[i].port);
sockfd = s.connect();
if (sockfd != NDB_INVALID_SOCKET) if (sockfd != NDB_INVALID_SOCKET)
break; break;
} }
...@@ -450,19 +514,17 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries, ...@@ -450,19 +514,17 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
break; break;
#ifndef DBUG_OFF #ifndef DBUG_OFF
{ {
char buf[1024];
DBUG_PRINT("info",("Unable to connect with connect string: %s", DBUG_PRINT("info",("Unable to connect with connect string: %s",
cfg.makeConnectString(buf,sizeof(buf)))); cfg.makeConnectString(buf,sizeof(buf))));
} }
#endif #endif
if (verbose > 0) { if (verbose > 0) {
char buf[1024]; fprintf(handle->errstream,
fprintf(handle->errstream, "Unable to connect with connect string: %s\n", "Unable to connect with connect string: %s\n",
cfg.makeConnectString(buf,sizeof(buf))); cfg.makeConnectString(buf,sizeof(buf)));
verbose= -1; verbose= -1;
} }
if (no_retries == 0) { if (no_retries == 0) {
char buf[1024];
setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__, setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
"Unable to connect with connect string: %s", "Unable to connect with connect string: %s",
cfg.makeConnectString(buf,sizeof(buf))); cfg.makeConnectString(buf,sizeof(buf)));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment