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:
committed by
Georgi Kodinov
parent
199a4dd2a9
commit
7322a6656a
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
67
mysql-test/main/resolveip.result
Normal file
67
mysql-test/main/resolveip.result
Normal 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
|
||||
#
|
||||
88
mysql-test/main/resolveip.test
Normal file
88
mysql-test/main/resolveip.test
Normal 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 #
|
||||
@@ -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
|
||||
# ----------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user