diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 33dd94d99f2..69045affee4 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1765,6 +1765,48 @@ static void set_root(const char *path) } +static my_socket create_socket(const struct addrinfo *addrinfo_list, + int addr_family, + struct addrinfo **use_addrinfo) +{ + my_socket sock= INVALID_SOCKET; + + for (const struct addrinfo *cur_ai= addrinfo_list; cur_ai != NULL; + cur_ai= cur_ai->ai_next) + { + if (cur_ai->ai_family != addr_family) + continue; + + sock= socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); + + char ip_addr[INET6_ADDRSTRLEN]; + + if (vio_get_normalized_ip_string(cur_ai->ai_addr, cur_ai->ai_addrlen, + ip_addr, sizeof (ip_addr))) + { + ip_addr[0]= 0; + } + + if (sock == INVALID_SOCKET) + { + sql_print_error("Failed to create a socket for %s '%s': errno: %d.", + (addr_family == AF_INET) ? "IPv4" : "IPv6", + (const char *) ip_addr, + (int) socket_errno); + continue; + } + + sql_print_information("Server socket created on IP: '%s'.", + (const char *) ip_addr); + + *use_addrinfo= (struct addrinfo *)cur_ai; + return sock; + } + + return INVALID_SOCKET; +} + + static void network_init(void) { #ifdef HAVE_SYS_UN_H @@ -1793,37 +1835,60 @@ static void network_init(void) { struct addrinfo *ai, *a; struct addrinfo hints; - int error; - DBUG_PRINT("general",("IP Socket is %d",mysqld_port)); + sql_print_information("Server hostname (bind-address): '%s'; port: %d", + my_bind_addr_str, mysqld_port); + + // Get list of IP-addresses associated with the server hostname. bzero(&hints, sizeof (hints)); hints.ai_flags= AI_PASSIVE; hints.ai_socktype= SOCK_STREAM; hints.ai_family= AF_UNSPEC; my_snprintf(port_buf, NI_MAXSERV, "%d", mysqld_port); - error= getaddrinfo(my_bind_addr_str, port_buf, &hints, &ai); - if (error != 0) + if (getaddrinfo(my_bind_addr_str, port_buf, &hints, &ai)) { - DBUG_PRINT("error",("Got error: %d from getaddrinfo()", error)); sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR)); /* purecov: tested */ + sql_print_error("Can't start server: cannot resolve hostname!"); unireg_abort(1); /* purecov: tested */ } - for (a= ai; a != NULL; a= a->ai_next) + // Log all the IP-addresses. + for (struct addrinfo *cur_ai= ai; cur_ai != NULL; cur_ai= cur_ai->ai_next) { - ip_sock= socket(a->ai_family, a->ai_socktype, a->ai_protocol); - if (ip_sock != INVALID_SOCKET) - break; + char ip_addr[INET6_ADDRSTRLEN]; + + if (vio_get_normalized_ip_string(cur_ai->ai_addr, cur_ai->ai_addrlen, + ip_addr, sizeof (ip_addr))) + { + sql_print_error("Fails to print out IP-address."); + continue; + } + + sql_print_information(" - '%s' resolves to '%s';", + my_bind_addr_str, ip_addr); } + /* + If the 'bind-address' option specifies the hostname, which resolves to + multiple IP-address, use the following rule: + - if there are IPv4-addresses, use the first IPv4-address + returned by getaddrinfo(); + - if there are IPv6-addresses, use the first IPv6-address + returned by getaddrinfo(); + */ + + ip_sock= create_socket(ai, AF_INET, &a); + + if (ip_sock == INVALID_SOCKET) + ip_sock= create_socket(ai, AF_INET6, &a); + + // Report user-error if we failed to create a socket. if (ip_sock == INVALID_SOCKET) { - DBUG_PRINT("error",("Got error: %d from socket()",socket_errno)); sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR)); /* purecov: tested */ - unireg_abort(1); /* purecov: tested */ + unireg_abort(1); /* purecov: tested */ } - #ifndef __WIN__ /* We should not use SO_REUSEADDR on windows as this would enable a @@ -7027,28 +7092,6 @@ mysqld_get_one_option(int optid, case (int) OPT_SKIP_STACK_TRACE: test_flags|=TEST_NO_STACKTRACE; break; - case (int) OPT_BIND_ADDRESS: - { - struct addrinfo *res_lst, hints; - - bzero(&hints, sizeof(struct addrinfo)); - hints.ai_socktype= SOCK_STREAM; - hints.ai_protocol= IPPROTO_TCP; - - if (getaddrinfo(argument, NULL, &hints, &res_lst) != 0) - { - sql_print_error("Can't start server: cannot resolve hostname!"); - return 1; - } - - if (res_lst->ai_next) - { - sql_print_error("Can't start server: bind-address refers to multiple interfaces!"); - return 1; - } - freeaddrinfo(res_lst); - } - break; case OPT_CONSOLE: if (opt_console) opt_error_log= 0; // Force logs to stdout