@@ -3501,7 +3501,6 @@ int MgmtSrvr::alloc_node_id_req(NodeId free_node_id,
35013501}
35023502
35033503enum class HostnameMatch {
3504- no_resolve, // failure: could not resolve hostname
35053504 no_match, // failure: hostname does not match socket address
35063505 ok_exact_match, // success: exact match
35073506 ok_wildcard, // success: match not required
@@ -3519,7 +3518,7 @@ static HostnameMatch match_hostname(const ndb_sockaddr *client_addr,
35193518 // - compare the resolved address with the clients.
35203519 ndb_sockaddr resolved_addr;
35213520 if (Ndb_getAddr (&resolved_addr, config_hostname) != 0 )
3522- return HostnameMatch::no_resolve ;
3521+ return HostnameMatch::no_match ;
35233522
35243523 // Special case for client connecting on loopback address, check if it
35253524 // can use this hostname by trying to bind the configured hostname. If this
@@ -3543,14 +3542,16 @@ static HostnameMatch match_hostname(const ndb_sockaddr *client_addr,
35433542/* *
35443543 @brief Build list of nodes in configuration
35453544
3545+ @param node_id 0 for any, otherwise a specific node id
3546+ @param type Type of nodes to list (MGM/DATA/API)
35463547 @param config_nodes List of nodes
3548+ @param error_code Error code
3549+ @param error_string Error string
35473550 @return true if list was filled properly, false otherwise
35483551 */
3549- bool MgmtSrvr::build_node_list_from_config (NodeId node_id,
3550- ndb_mgm_node_type type,
3551- Vector<ConfigNode> &config_nodes,
3552- int &error_code,
3553- BaseString &error_string) const {
3552+ bool MgmtSrvr::build_node_type_list_from_config (
3553+ NodeId node_id, ndb_mgm_node_type type, Vector<ConfigNode> &config_nodes,
3554+ int &error_code, BaseString &error_string) const {
35543555 Guard g (m_local_config_mutex);
35553556
35563557 ConfigIter iter (m_local_config, CFG_SECTION_NODE);
@@ -3604,13 +3605,42 @@ bool MgmtSrvr::build_node_list_from_config(NodeId node_id,
36043605 return true ;
36053606}
36063607
3607- int MgmtSrvr::find_node_type (NodeId node_id, ndb_mgm_node_type type,
3608- const ndb_sockaddr *client_addr,
3609- const Vector<ConfigNode> &config_nodes,
3610- Vector<PossibleNode> &nodes, int &error_code,
3611- BaseString &error_string) {
3612- const char *found_config_hostname = nullptr ;
3613- bool found_unresolved_hosts = false ;
3608+ /* *
3609+ Given a list of nodes from config, find all that match the
3610+ supplied client address and (optional) node id
3611+
3612+ @param node_id If non zero then specifies required nodeid. Can only be
3613+ one match.
3614+ If zero then any nodeid matches, return all.
3615+ @param type Type of node being matched (DB|MGMD|API)
3616+ @param client_addr Address client is connecting from
3617+ @param config_nodes List of nodes matching type from config
3618+ @param nodes Output list of nodes matching client address
3619+ */
3620+ void MgmtSrvr::match_client_addr_to_config_nodes (
3621+ NodeId node_id, ndb_mgm_node_type type, const ndb_sockaddr *client_addr,
3622+ const Vector<ConfigNode> &config_nodes,
3623+ Vector<PossibleNode> &node_matches) {
3624+ /* *
3625+ * Examine every candidate node from config to see if it can
3626+ * be a match for the connecting client's address.
3627+ *
3628+ * If node_id is specified then we return the first match.
3629+ * If node_id is not specified then all matches are returned
3630+ *
3631+ * Types of config vs client address match :
3632+ * Wildcard match : Config has no address - matches anything
3633+ * Exact match : Config has address which matches client's when
3634+ * resolved (can also be loopback)
3635+ * No match : Config has address which does not match client's
3636+ * when resolved.
3637+ *
3638+ * The resulting vector of matching nodes can be length :
3639+ * 0 No config nodes match client address
3640+ * 1 One config node matches client address
3641+ * >1 Multiple config nodes match client address
3642+ * Exact matches are placed first in the Vector
3643+ */
36143644
36153645 for (unsigned i = 0 ; i < config_nodes.size (); i++) {
36163646 const ConfigNode &node = config_nodes[i];
@@ -3625,97 +3655,35 @@ int MgmtSrvr::find_node_type(NodeId node_id, ndb_mgm_node_type type,
36253655 const HostnameMatch matchType =
36263656 match_hostname (client_addr, config_hostname);
36273657 switch (matchType) {
3628- case HostnameMatch::no_resolve:
3629- found_config_hostname = config_hostname;
3630- found_unresolved_hosts = true ;
3631- break ;
3632-
36333658 case HostnameMatch::no_match:
3634- found_config_hostname = config_hostname;
3659+ /* Config address not resolvable or resolvable and
3660+ * - Client address is loopback but we cannot bind the config address
3661+ * - Client address and resolved config are not IPv6 equal
3662+ */
36353663 break ;
36363664
36373665 case HostnameMatch::ok_wildcard:
3638- nodes.push_back ({current_node_id, " " , false });
3666+ /* Config hostname is null or empty */
3667+ node_matches.push_back ({current_node_id, " " , false });
36393668 break ;
36403669
36413670 case HostnameMatch::ok_exact_match: {
3642- found_config_hostname = config_hostname;
3643-
3671+ /* Config address resolvable
3672+ * - Client address is loopback and we can bind the config address
3673+ * - Client address and resolved config are IPv6 equal
3674+ */
36443675 unsigned int pos = 0 ;
36453676 // Insert this node into the list ahead of the non-exact matches
3646- for (; pos < nodes.size () && nodes[pos].exact_match ; pos++)
3677+ for (; pos < node_matches.size () && node_matches[pos].exact_match ;
3678+ pos++)
36473679 ;
3648- nodes .push ({current_node_id, config_hostname, true }, pos);
3680+ node_matches .push ({current_node_id, config_hostname, true }, pos);
36493681 break ;
36503682 }
36513683 }
36523684
3653- if (node_id) break ;
3654- }
3655-
3656- if (nodes.size () != 0 ) {
3657- return 0 ;
3658- }
3659-
3660- if (found_unresolved_hosts) {
3661- error_code = NDB_MGM_ALLOCID_CONFIG_RETRY;
3662-
3663- BaseString type_string;
3664- const char *alias, *str = nullptr ;
3665- char addr_buf[NDB_ADDR_STRLEN];
3666- alias = ndb_mgm_get_node_type_alias_string (type, &str);
3667- type_string.assfmt (" %s(%s)" , alias, str);
3668-
3669- char *addr_str = Ndb_inet_ntop (client_addr, addr_buf, sizeof (addr_buf));
3670-
3671- error_string.appfmt (
3672- " No configured host found of node type %s for "
3673- " connection from ip %s. Some hostnames are currently "
3674- " unresolvable. Can be retried." ,
3675- type_string.c_str (), addr_str);
3676- return -1 ;
3685+ if (node_id) break ; /* Found the only match */
36773686 }
3678-
3679- /*
3680- lock on m_configMutex held because found_config_hostname may have
3681- reference into config structure
3682- */
3683- error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
3684- if (node_id) {
3685- if (found_config_hostname) {
3686- char addr_buf[NDB_ADDR_STRLEN];
3687- {
3688- // Append error describing which host the faulty connection was from
3689- char *addr_str = Ndb_inet_ntop (client_addr, addr_buf, sizeof (addr_buf));
3690- error_string.appfmt (" Connection with id %d done from wrong host ip %s," ,
3691- node_id, addr_str);
3692- }
3693- {
3694- // Append error describing which was the expected host
3695- ndb_sockaddr config_addr;
3696- int r_config_addr = Ndb_getAddr (&config_addr, found_config_hostname);
3697- char *addr_str =
3698- Ndb_inet_ntop (&config_addr, addr_buf, sizeof (addr_buf));
3699- error_string.appfmt (" expected %s(%s)." , found_config_hostname,
3700- r_config_addr ? " lookup failed" : addr_str);
3701- }
3702- return -1 ;
3703- }
3704- error_string.appfmt (" No node defined with id=%d in config file." , node_id);
3705- return -1 ;
3706- }
3707-
3708- // node_id == 0 and nodes.size() == 0
3709- if (found_config_hostname) {
3710- char addr_buf[NDB_ADDR_STRLEN];
3711- char *addr_str = Ndb_inet_ntop (client_addr, addr_buf, sizeof (addr_buf));
3712- error_string.appfmt (" Connection done from wrong host ip %s." ,
3713- (client_addr) ? addr_str : " " );
3714- return -1 ;
3715- }
3716-
3717- error_string.append (" No nodes defined in config file." );
3718- return -1 ;
37193687}
37203688
37213689int MgmtSrvr::try_alloc (NodeId id, ndb_mgm_node_type type, Uint32 timeout_ms,
@@ -3894,21 +3862,73 @@ bool MgmtSrvr::alloc_node_id_impl(NodeId &nodeid, enum ndb_mgm_node_type type,
38943862 }
38953863 }
38963864
3897- // Build list of nodes fom configuration, this is done as a separate step
3898- // in order to hold the config mutex only for a short time and also
3899- // avoid holding it while resolving addresses.
3865+ // Build list of nodes matching (type[, nodeid]), from configuration,
3866+ // this is done as a separate step in order to hold the config mutex
3867+ // only for a short time and also avoid holding it while resolving
3868+ // addresses.
39003869 Vector<ConfigNode> config_nodes;
3901- if (!build_node_list_from_config (nodeid, type, config_nodes, error_code,
3902- error_string)) {
3870+ if (!build_node_type_list_from_config (nodeid, type, config_nodes, error_code,
3871+ error_string)) {
39033872 assert (error_string.length () > 0 );
39043873 return false ;
39053874 }
39063875
3907- /* Find possible nodeids */
3876+ if (config_nodes.size () == 0 ) {
3877+ /* No nodes in config matching type [and nodeid] */
3878+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
3879+ if (nodeid != 0 ) {
3880+ error_string.appfmt (" No node defined with id=%d in config file." , nodeid);
3881+ return false ;
3882+ } else {
3883+ error_string.append (" No nodes defined in config file." );
3884+ return false ;
3885+ }
3886+ }
3887+
3888+ /* Choose subset of candidates matching client address */
39083889 Vector<PossibleNode> nodes;
3909- if (find_node_type (nodeid, type, client_addr, config_nodes, nodes, error_code,
3910- error_string))
3890+ match_client_addr_to_config_nodes (nodeid, type, client_addr, config_nodes,
3891+ nodes);
3892+
3893+ if (nodes.size () == 0 ) {
3894+ /* *
3895+ * No candidate node ids matched client address
3896+ *
3897+ * This could indicate :
3898+ * 1 Temporary name resolution misalignment
3899+ * 2 Permanent name resolution misalignment
3900+ * 3 Attempt to connect from incorrect location
3901+ *
3902+ * To cover case 1, a temporary 'retry' error is returned rather
3903+ * than a permanent error.
3904+ */
3905+ error_code = NDB_MGM_ALLOCID_CONFIG_RETRY;
3906+ char addr_buf[NDB_ADDR_STRLEN];
3907+ char *addr_str = Ndb_inet_ntop (client_addr, addr_buf, sizeof (addr_buf));
3908+
3909+ if (nodeid != 0 ) {
3910+ // Append error describing which host the faulty connection was from
3911+ error_string.appfmt (" Connection with id %d done from host ip %s," , nodeid,
3912+ addr_str);
3913+
3914+ // Append error describing which was the expected host
3915+ ndb_sockaddr config_addr;
3916+ assert (config_nodes.size () == 1 ); /* Single matching nodeid from config */
3917+ const char *config_hostname = config_nodes[0 ].hostname .c_str ();
3918+ int r_config_addr = Ndb_getAddr (&config_addr, config_hostname);
3919+ char *addr_str = Ndb_inet_ntop (&config_addr, addr_buf, sizeof (addr_buf));
3920+ error_string.appfmt (" not matching expected %s(%s)." , config_hostname,
3921+ r_config_addr ? " lookup failed" : addr_str);
3922+ } else {
3923+ /* nodeid == 0 */
3924+ error_string.appfmt (
3925+ " Connection done from host ip %s, not matching any (resolved) "
3926+ " configured address." ,
3927+ (client_addr) ? addr_str : " " );
3928+ }
3929+
39113930 return false ;
3931+ }
39123932
39133933 // Print list of possible nodes
39143934 for (unsigned i = 0 ; i < nodes.size (); i++) {
@@ -3917,7 +3937,7 @@ bool MgmtSrvr::alloc_node_id_impl(NodeId &nodeid, enum ndb_mgm_node_type type,
39173937 node.host .c_str (), node.exact_match );
39183938 }
39193939
3920- // nodes.size() == 0 handled inside find_node_type
3940+ // nodes.size() == 0 handled above
39213941 assert (nodes.size () != 0 );
39223942
39233943 if (type == NDB_MGM_NODE_TYPE_MGM && nodes.size () > 1 ) {
0 commit comments