1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00

MDEV-39169 Replace deprecated network functions in resolveip

Replace inet_aton/inet_addr/gethostbyname/gethostbyaddr with
their modern POSIX equivalents inet_pton/getaddrinfo/getnameinfo.
This adds IPv6 support to resolveip and removes dependency on the
deprecated h_errno global.

Handle IPv6 unspecified address (::) as Null-IP-Addr, consistent
with existing IPv4 INADDR_ANY handling for 0.0.0.0.

Add MTR test covering IPv4/IPv6 reverse lookups, special
addresses, multiple arguments, mixed address types, and
invalid hostname handling.

Co-Authored-By: Claude AI <noreply@anthropic.com>
This commit is contained in:
Michal Schorm
2026-03-27 15:30:24 +01:00
committed by Georgi Kodinov
parent 199a4dd2a9
commit 7322a6656a
5 changed files with 276 additions and 73 deletions

View File

@@ -123,7 +123,7 @@ TARGET_LINK_LIBRARIES(resolveip mysys)
IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
INCLUDE(CheckFunctionExists)
INCLUDE(CheckLibraryExists)
MY_SEARCH_LIBS(inet_aton "nsl;socket;resolv" SOLARIS_NSL)
MY_SEARCH_LIBS(getaddrinfo "nsl;socket;resolv" SOLARIS_NSL)
TARGET_LINK_LIBRARIES(resolveip ${SOLARIS_NSL})
ENDIF()
ENDIF()

View File

@@ -16,7 +16,7 @@
/* Resolves IP's to hostname and hostnames to IP's */
#define VER "2.3"
#define VER "2.4"
#include <my_global.h>
#include <m_ctype.h>
@@ -33,9 +33,6 @@
#include <my_getopt.h>
#include <welcome_copyright_notice.h>
#if !defined(_AIX) && !defined(h_errno)
extern int h_errno;
#endif
static my_bool silent;
@@ -104,9 +101,7 @@ static int get_options(int *argc,char ***argv)
int main(int argc, char **argv)
{
struct hostent *hpaddr;
in_addr_t taddr;
char *ip,**q;
char *ip;
int error=0;
MY_INIT(argv[0]);
@@ -119,92 +114,135 @@ int main(int argc, char **argv)
while (argc--)
{
my_bool do_more;
#ifndef WIN32
struct in_addr addr;
#endif
ip = *argv++;
struct in_addr addr4;
struct in6_addr addr6;
int is_ipv4, is_ipv6;
/* Not compatible with IPv6! Probably should use getnameinfo(). */
#ifdef WIN32
taddr = inet_addr(ip);
do_more= (taddr != INADDR_NONE);
#else
if ((do_more= (inet_aton(ip, &addr) != 0)))
taddr= addr.s_addr;
#endif
if (do_more)
ip = *argv++;
is_ipv4= (inet_pton(AF_INET, ip, &addr4) == 1);
is_ipv6= (!is_ipv4 && inet_pton(AF_INET6, ip, &addr6) == 1);
if (is_ipv4 || is_ipv6)
{
if (taddr == htonl(INADDR_BROADCAST))
{
puts("Broadcast");
continue;
}
if (taddr == htonl(INADDR_ANY))
{
if (!taddr)
puts("Null-IP-Addr");
else
puts("Old-Bcast");
continue;
}
/* Reverse lookup: IP address -> hostname */
hpaddr = gethostbyaddr((char*) &(taddr), sizeof(struct in_addr),AF_INET);
if (hpaddr)
if (is_ipv4)
{
if (silent)
puts(hpaddr->h_name);
else
in_addr_t taddr= addr4.s_addr;
if (taddr == htonl(INADDR_BROADCAST))
{
printf ("Host name of %s is %s", ip,hpaddr->h_name);
for (q = hpaddr->h_aliases; *q != 0; q++)
(void) printf(", %s", *q);
puts("");
puts("Broadcast");
continue;
}
if (taddr == htonl(INADDR_ANY))
{
if (!taddr)
puts("Null-IP-Addr");
else
puts("Old-Bcast");
continue;
}
}
else
else if (IN6_IS_ADDR_UNSPECIFIED(&addr6))
{
error=2;
fprintf(stderr,"%s: Unable to find hostname for '%s'\n",my_progname,
ip);
puts("Null-IP-Addr");
continue;
}
{
struct sockaddr_storage sa;
socklen_t sa_len;
char hostname[NI_MAXHOST];
int err;
memset(&sa, 0, sizeof(sa));
if (is_ipv4)
{
struct sockaddr_in *sa4= (struct sockaddr_in *) &sa;
sa4->sin_family= AF_INET;
sa4->sin_addr= addr4;
sa_len= sizeof(struct sockaddr_in);
}
else
{
struct sockaddr_in6 *sa6= (struct sockaddr_in6 *) &sa;
sa6->sin6_family= AF_INET6;
sa6->sin6_addr= addr6;
sa_len= sizeof(struct sockaddr_in6);
}
err= getnameinfo((struct sockaddr *) &sa, sa_len,
hostname, sizeof(hostname), NULL, 0, NI_NAMEREQD);
if (err == 0)
{
if (silent)
puts(hostname);
else
printf("Host name of %s is %s\n", ip, hostname);
}
else
{
error= 2;
fflush(stdout);
fprintf(stderr, "%s: Unable to find hostname for '%s'\n",
my_progname, ip);
}
}
}
else
{
hpaddr = gethostbyname(ip);
if (!hpaddr)
/* Forward lookup: hostname -> IP address(es) */
struct addrinfo hints, *res, *rp;
int err;
memset(&hints, 0, sizeof(hints));
hints.ai_family= AF_UNSPEC;
hints.ai_socktype= SOCK_STREAM;
err= getaddrinfo(ip, NULL, &hints, &res);
if (err != 0)
{
const char *err;
fprintf(stderr,"%s: Unable to find hostid for '%s'",my_progname,ip);
switch (h_errno) {
case HOST_NOT_FOUND: err="host not found"; break;
case TRY_AGAIN: err="try again"; break;
case NO_RECOVERY: err="no recovery"; break;
case NO_DATA: err="no_data"; break;
default: err=0;
}
if (err)
fprintf(stderr,": %s\n",err);
else
fprintf(stderr,"\n");
error=2;
fflush(stdout);
fprintf(stderr, "%s: Unable to find hostid for '%s': %s\n",
my_progname, ip, gai_strerror(err));
error= 2;
}
else if (silent)
{
struct in_addr in;
memcpy((char*) &in.s_addr, (char*) *hpaddr->h_addr_list,
sizeof (in.s_addr));
puts(inet_ntoa(in));
char addr_str[INET6_ADDRSTRLEN];
const void *addr_ptr;
if (res->ai_family == AF_INET)
addr_ptr= &((struct sockaddr_in *) res->ai_addr)->sin_addr;
else
addr_ptr= &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
if (inet_ntop(res->ai_family, addr_ptr, addr_str, sizeof(addr_str)))
puts(addr_str);
freeaddrinfo(res);
}
else
{
char **p;
for (p = hpaddr->h_addr_list; *p != 0; p++)
for (rp= res; rp != NULL; rp= rp->ai_next)
{
struct in_addr in;
memcpy(&in.s_addr, *p, sizeof (in.s_addr));
printf ("IP address of %s is %s\n",ip,inet_ntoa(in));
char addr_str[INET6_ADDRSTRLEN];
const void *addr_ptr;
if (rp->ai_family == AF_INET)
addr_ptr= &((struct sockaddr_in *) rp->ai_addr)->sin_addr;
else if (rp->ai_family == AF_INET6)
addr_ptr= &((struct sockaddr_in6 *) rp->ai_addr)->sin6_addr;
else
continue;
if (inet_ntop(rp->ai_family, addr_ptr, addr_str, sizeof(addr_str)))
printf("IP address of %s is %s\n", ip, addr_str);
}
freeaddrinfo(res);
}
}
}

View File

@@ -0,0 +1,67 @@
#
# MDEV-39169: resolveip IPv6 support
#
#
# IPv4 special addresses (deterministic, no DNS needed)
#
Broadcast
Null-IP-Addr
#
# IPv4 reverse lookup
#
Host name of 127.0.0.1 is HOSTNAME
#
# IPv4 reverse lookup (silent mode)
#
HOSTNAME
#
# IPv6 special address (deterministic, no DNS needed)
#
Null-IP-Addr
#
# IPv6 unspecified address (full form)
#
Null-IP-Addr
#
# IPv6 reverse lookup
#
Host name of ::1 is HOSTNAME
#
# IPv6 reverse lookup (silent mode)
#
HOSTNAME
#
# IPv6 IPv4-mapped address
#
Host name of ::ffff:127.0.0.1 is HOSTNAME
#
# IPv6 full form address
#
Host name of 0000:0000:0000:0000:0000:0000:0000:0001 is HOSTNAME
#
# Multiple addresses in one call
#
Broadcast
Null-IP-Addr
#
# Mixed IPv4 and IPv6 addresses
#
Broadcast
Null-IP-Addr
#
# Mixed IP address and hostname
#
REPLACED
REPLACED
#
# Invalid hostname
#
resolveip: Unable to find hostid for 'nonexistent.invalid': NAME_RESOLUTION_ERROR
#
# Invalid address mixed with valid address
#
Broadcast
resolveip: Unable to find hostid for 'nonexistent.invalid': NAME_RESOLUTION_ERROR
#
# End of 13.0 tests
#

View File

@@ -0,0 +1,88 @@
--source include/not_windows.inc
--source include/check_ipv6.inc
# Reverse DNS tests (getnameinfo with NI_NAMEREQD) require:
# - /etc/hosts entries for 127.0.0.1 and ::1 (or working DNS PTR records)
# - "hosts: files ..." in /etc/nsswitch.conf (or equivalent resolver config)
# - glibc nss_files backend mapping ::ffff:127.0.0.1 to the 127.0.0.1 entry
# - - musl libc (Alpine) may behave differently from glibc for mapped addresses
# If reverse lookups fail, check: getent hosts 127.0.0.1 ::1 ::ffff:127.0.0.1
--echo #
--echo # MDEV-39169: resolveip IPv6 support
--echo #
--echo #
--echo # IPv4 special addresses (deterministic, no DNS needed)
--echo #
--exec $MYSQL_RESOLVEIP 255.255.255.255
--exec $MYSQL_RESOLVEIP 0.0.0.0
--echo #
--echo # IPv4 reverse lookup
--echo #
--exec $MYSQL_RESOLVEIP 127.0.0.1 2>&1 | sed 's/Host name of 127\.0\.0\.1 is .*/Host name of 127.0.0.1 is HOSTNAME/'
--echo #
--echo # IPv4 reverse lookup (silent mode)
--echo #
--exec $MYSQL_RESOLVEIP -s 127.0.0.1 2>&1 | sed 's/.*/HOSTNAME/'
--echo #
--echo # IPv6 special address (deterministic, no DNS needed)
--echo #
--exec $MYSQL_RESOLVEIP ::
--echo #
--echo # IPv6 unspecified address (full form)
--echo #
--exec $MYSQL_RESOLVEIP 0000:0000:0000:0000:0000:0000:0000:0000
--echo #
--echo # IPv6 reverse lookup
--echo #
--exec $MYSQL_RESOLVEIP ::1 2>&1 | sed 's/Host name of ::1 is .*/Host name of ::1 is HOSTNAME/'
--echo #
--echo # IPv6 reverse lookup (silent mode)
--echo #
--exec $MYSQL_RESOLVEIP -s ::1 2>&1 | sed 's/.*/HOSTNAME/'
--echo #
--echo # IPv6 IPv4-mapped address
--echo #
--exec $MYSQL_RESOLVEIP ::ffff:127.0.0.1 2>&1 | sed 's/Host name of ::ffff:127\.0\.0\.1 is .*/Host name of ::ffff:127.0.0.1 is HOSTNAME/'
--echo #
--echo # IPv6 full form address
--echo #
--exec $MYSQL_RESOLVEIP 0000:0000:0000:0000:0000:0000:0000:0001 2>&1 | sed 's/Host name of 0000:0000:0000:0000:0000:0000:0000:0001 is .*/Host name of 0000:0000:0000:0000:0000:0000:0000:0001 is HOSTNAME/'
--echo #
--echo # Multiple addresses in one call
--echo #
--exec $MYSQL_RESOLVEIP 255.255.255.255 0.0.0.0
--echo #
--echo # Mixed IPv4 and IPv6 addresses
--echo #
--exec $MYSQL_RESOLVEIP 255.255.255.255 ::
--echo #
--echo # Mixed IP address and hostname
--echo #
--exec $MYSQL_RESOLVEIP -s 127.0.0.1 localhost | sed 's/.*/REPLACED/'
--echo #
--echo # Invalid hostname
--echo #
--exec $MYSQL_RESOLVEIP nonexistent.invalid 2>&1 | sed "s|.*Unable to find hostid for 'nonexistent.invalid': .*|resolveip: Unable to find hostid for 'nonexistent.invalid': NAME_RESOLUTION_ERROR|"
--echo #
--echo # Invalid address mixed with valid address
--echo #
--exec $MYSQL_RESOLVEIP 255.255.255.255 nonexistent.invalid 2>&1 | sed "s|.*Unable to find hostid for 'nonexistent.invalid': .*|resolveip: Unable to find hostid for 'nonexistent.invalid': NAME_RESOLUTION_ERROR|"
--echo #
--echo # End of 13.0 tests
--echo #

View File

@@ -2294,6 +2294,16 @@ sub environment_setup {
"$path_client_bindir/mariadb-migrate-config-file");
$ENV{'MARIADB_MIGRATE_CONFIG_FILE'}= native_path($exe_mariadb_migrate_config_file) if $exe_mariadb_migrate_config_file;
# ----------------------------------------------------
# resolveip (not built on Windows)
# ----------------------------------------------------
unless (IS_WINDOWS) {
my $exe_resolveip=
mtr_exe_exists("$bindir/extra$multiconfig/resolveip",
"$path_client_bindir/resolveip");
$ENV{'MYSQL_RESOLVEIP'}= native_path($exe_resolveip);
}
# ----------------------------------------------------
# myisam tools
# ----------------------------------------------------