===== include/mgmapi/mgmapi.h 1.49 vs edited ===== --- 1.49/ndb/include/mgmapi/mgmapi.h 2006-09-11 22:11:51 +02:00 +++ include/mgmapi/mgmapi.h 2006-09-11 14:20:47 +02:00 @@ -231,7 +231,9 @@ NDB_MGM_SERVER_NOT_CONNECTED = 1010, /** Could not connect to socker */ NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET = 1011, - + /** Could not bind local address */ + NDB_MGM_BIND_ADDRESS = 1012, + /* Alloc node id failures */ /** Generic error, retry may succeed */ NDB_MGM_ALLOCID_ERROR = 1101, @@ -514,6 +516,15 @@ int ndb_mgm_get_connected_port(NdbMgmHandle handle); const char *ndb_mgm_get_connected_host(NdbMgmHandle handle); 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 ===== include/mgmcommon/ConfigRetriever.hpp 1.18 vs edited ===== --- 1.18/ndb/include/mgmcommon/ConfigRetriever.hpp 2006-09-11 22:11:51 +02:00 +++ include/mgmcommon/ConfigRetriever.hpp 2006-09-11 13:39:44 +02:00 @@ -28,7 +28,8 @@ class ConfigRetriever { public: ConfigRetriever(const char * _connect_string, - Uint32 version, Uint32 nodeType); + Uint32 version, Uint32 nodeType, + const char * _bind_address = 0); ~ConfigRetriever(); int do_connect(int no_retries, int retry_delay_in_seconds, int verbose); ===== include/util/SocketClient.hpp 1.4 vs edited ===== --- 1.4/ndb/include/util/SocketClient.hpp 2006-09-11 22:11:51 +02:00 +++ include/util/SocketClient.hpp 2006-09-11 14:18:13 +02:00 @@ -37,7 +37,8 @@ }; unsigned short get_port() { return m_port; }; 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(); }; ===== src/common/mgmcommon/ConfigRetriever.cpp 1.34 vs edited ===== --- 1.34/ndb/src/common/mgmcommon/ConfigRetriever.cpp 2006-09-11 22:11:51 +02:00 +++ src/common/mgmcommon/ConfigRetriever.cpp 2006-09-11 13:40:58 +02:00 @@ -45,7 +45,8 @@ //**************************************************************************** ConfigRetriever::ConfigRetriever(const char * _connect_string, - Uint32 version, Uint32 node_type) + Uint32 version, Uint32 node_type, + const char * _bindaddress) { DBUG_ENTER("ConfigRetriever::ConfigRetriever"); @@ -65,6 +66,15 @@ { setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle)); 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(); DBUG_VOID_RETURN; ===== src/common/util/SocketClient.cpp 1.7 vs edited ===== --- 1.7/ndb/src/common/util/SocketClient.cpp 2006-09-11 22:11:51 +02:00 +++ src/common/util/SocketClient.cpp 2006-09-11 22:00:21 +02:00 @@ -25,7 +25,7 @@ { m_auth= sa; m_port= port; - m_server_name= strdup(server_name); + m_server_name= server_name ? strdup(server_name) : 0; m_sockfd= NDB_INVALID_SOCKET; } @@ -45,13 +45,16 @@ if (m_sockfd != NDB_INVALID_SOCKET) NDB_CLOSE_SOCKET(m_sockfd); - memset(&m_servaddr, 0, sizeof(m_servaddr)); - m_servaddr.sin_family = AF_INET; - m_servaddr.sin_port = htons(m_port); - // Convert ip address presentation format to numeric format - if (Ndb_getInAddr(&m_servaddr.sin_addr, m_server_name)) - return false; - + if (m_server_name) + { + memset(&m_servaddr, 0, sizeof(m_servaddr)); + m_servaddr.sin_family = AF_INET; + m_servaddr.sin_port = htons(m_port); + // 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); if (m_sockfd == NDB_INVALID_SOCKET) { return false; @@ -62,8 +65,45 @@ 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 -SocketClient::connect() +SocketClient::connect(const char *toaddress, unsigned short toport) { if (m_sockfd == NDB_INVALID_SOCKET) { @@ -74,6 +114,21 @@ 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)); if (r == -1) { NDB_CLOSE_SOCKET(m_sockfd); ===== src/kernel/vm/Configuration.cpp 1.47 vs edited ===== --- 1.47/ndb/src/kernel/vm/Configuration.cpp 2006-09-11 22:11:51 +02:00 +++ src/kernel/vm/Configuration.cpp 2006-09-11 13:39:20 +02:00 @@ -58,7 +58,8 @@ // XXX should be my_bool ??? static int _daemon, _no_daemon, _foreground, _initial, _no_start; 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 NdbNodeBitmask g_nowait_nodes; @@ -98,6 +99,10 @@ "Perform initial start", (gptr*) &_initialstart, (gptr*) &_initialstart, 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} }; static void short_usage_sub(void) @@ -257,7 +262,9 @@ m_mgmd_port= 0; m_config_retriever= new ConfigRetriever(getConnectString(), - NDB_VERSION, NODE_TYPE_DB); + NDB_VERSION, + NODE_TYPE_DB, + _bind_address); if (m_config_retriever->hasError()) { ===== src/mgmapi/mgmapi.cpp 1.60 vs edited ===== --- 1.60/ndb/src/mgmapi/mgmapi.cpp 2006-09-11 22:11:51 +02:00 +++ src/mgmapi/mgmapi.cpp 2006-09-11 21:30:10 +02:00 @@ -107,6 +107,7 @@ int mgmd_version_major; int mgmd_version_minor; int mgmd_version_build; + char * m_bindaddress; }; #define SET_ERROR(h, e, s) setError(h, e, __LINE__, s) @@ -162,6 +163,7 @@ h->cfg_i = -1; h->errstream = stdout; h->m_name = 0; + h->m_bindaddress = 0; strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE); @@ -209,6 +211,22 @@ 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 */ @@ -235,6 +253,8 @@ #endif (*handle)->cfg.~LocalConfig(); 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)); * handle = 0; DBUG_VOID_RETURN; @@ -427,6 +447,7 @@ BaseString::snprintf(logname, 64, "mgmapi.log"); handle->logfile = fopen(logname, "w"); #endif + char buf[1024]; /** * Do connect @@ -434,6 +455,50 @@ LocalConfig &cfg= handle->cfg; NDB_SOCKET_TYPE sockfd= NDB_INVALID_SOCKET; 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) { // do all the mgmt servers @@ -441,8 +506,7 @@ { if (cfg.ids[i].type != MgmId_TCP) continue; - SocketClient s(cfg.ids[i].name.c_str(), cfg.ids[i].port); - sockfd = s.connect(); + sockfd = s.connect(cfg.ids[i].name.c_str(), cfg.ids[i].port); if (sockfd != NDB_INVALID_SOCKET) break; } @@ -450,19 +514,17 @@ break; #ifndef DBUG_OFF { - char buf[1024]; DBUG_PRINT("info",("Unable to connect with connect string: %s", cfg.makeConnectString(buf,sizeof(buf)))); } #endif if (verbose > 0) { - char buf[1024]; - fprintf(handle->errstream, "Unable to connect with connect string: %s\n", + fprintf(handle->errstream, + "Unable to connect with connect string: %s\n", cfg.makeConnectString(buf,sizeof(buf))); verbose= -1; } if (no_retries == 0) { - char buf[1024]; setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__, "Unable to connect with connect string: %s", cfg.makeConnectString(buf,sizeof(buf)));