Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inet_aton in Socket.pm core module is broken #11169

Open
p5pRT opened this issue Mar 2, 2011 · 23 comments
Open

inet_aton in Socket.pm core module is broken #11169

p5pRT opened this issue Mar 2, 2011 · 23 comments

Comments

@p5pRT
Copy link

p5pRT commented Mar 2, 2011

Migrated from rt.perl.org#85308 (status was 'open')

Searchable as RT85308$

@p5pRT
Copy link
Author

p5pRT commented Mar 2, 2011

From quanah@zimbra.com

Created by quanah@zimbra.com

This is a bug report for perl from quanah@​zimbra.com,
generated with the help of perlbug 1.39 running under perl 5.10.1.

-----------------------------------------------------------------
In testing IPv4 and IPv6, we have found that if the IPv4 address in the
/etc/host file appears after the IPv6 configuration, the inet_aton call in
Socket.pm/Socket.so that is part of the core perl build fails to correctly
resolve the IPv4 address, breaking any module that uses inet_aton and IPv4
lookups. If the IPv4 address is moved to occur before the IPv6
configuration in /etc/hosts, then the the inet_aton call from
Socket.pm/Socket.so succeeds. I have found nothing RFC or otherwise that
fixes the location of IPv4 addresses in /etc/hosts as being required to
occur before IPv6, and the fact that other IPv4 programs can function just
fine with the IPv4 after IPv6 configuration, indicates this is definitely
an issue with how Perl has implemented the function.

Perl Info

Flags:
    category=library
    severity=critical
    module=Socket

Site configuration information for perl 5.10.1:

Configured by Debian Project at Fri Apr 23 08:18:41 UTC 2010.

Summary of my perl5 (revision 5 version 10 subversion 1) configuration:

  Platform:
    osname=linux, osvers=2.6.24-27-server, 
archname=x86_64-linux-gnu-thread-multi
    uname='linux crested 2.6.24-27-server #1 smp fri mar 12 01:23:09 utc 
2010 x86_64 gnulinux '
    config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN 
-Dcccdlflags=-fPIC -Darchname=x86_64-linux-gnu -Dprefix=/usr 
-Dprivlib=/usr/share/perl/5.10 -Darchlib=/usr/lib/perl/5.10 
-Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 
-Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local 
-Dsitelib=/usr/local/share/perl/5.10.1 
-Dsitearch=/usr/local/lib/perl/5.10.1 -Dman1dir=/usr/share/man/man1 
-Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 
-Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl 
-Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Ud_ualarm -Uusesfio -Uusenm 
-DDEBUGGING=-g -Doptimize=-O2 -Duseshrplib -Dlibperl=libperl.so.5.10.1 
-Dd_dosuid -des'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN 
-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include 
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -g',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing 
-pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.4.3', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', 
lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib /lib64 /usr/lib64
    libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
    perllibs=-ldl -lm -lpthread -lc -lcrypt
    libc=/lib/libc-2.11.1.so, so=so, useshrplib=true, 
libperl=libperl.so.5.10.1
    gnulibc_version='2.11.1'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -g -L/usr/local/lib 
-fstack-protector'

Locally applied patches:



@INC for perl 5.10.1:
    /etc/perl
    /usr/local/lib/perl/5.10.1
    /usr/local/share/perl/5.10.1
    /usr/lib/perl5
    /usr/share/perl5
    /usr/lib/perl/5.10
    /usr/share/perl/5.10
    /usr/local/lib/site_perl
    .


Environment for perl 5.10.1:
    HOME=/home/quanah
    LANG=C
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
 
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/quanah/bin:/usr/local/java/bin:/usr/local/ant/bin
    PERL_BADLANG (unset)
    SHELL=/bin/bash


--

Quanah Gibson-Mount
Sr. Member of Technical Staff
Zimbra, Inc
A Division of VMware, Inc.
--------------------
Zimbra ::  the leader in open source messaging and collaboration

@p5pRT
Copy link
Author

p5pRT commented Mar 4, 2011

From @smpeters

On Wed Mar 02 15​:35​:49 2011, quanah@​zimbra.com wrote​:

This is a bug report for perl from quanah@​zimbra.com,
generated with the help of perlbug 1.39 running under perl 5.10.1.

-----------------------------------------------------------------
In testing IPv4 and IPv6, we have found that if the IPv4 address in
the
/etc/host file appears after the IPv6 configuration, the inet_aton
call in
Socket.pm/Socket.so that is part of the core perl build fails to
correctly
resolve the IPv4 address, breaking any module that uses inet_aton and
IPv4
lookups. If the IPv4 address is moved to occur before the IPv6
configuration in /etc/hosts, then the the inet_aton call from
Socket.pm/Socket.so succeeds. I have found nothing RFC or otherwise
that
fixes the location of IPv4 addresses in /etc/hosts as being required
to
occur before IPv6, and the fact that other IPv4 programs can function
just
fine with the IPv4 after IPv6 configuration, indicates this is
definitely
an issue with how Perl has implemented the function.

Can you provide some sample code along with what operating system this
is along with the versions of Perl and Socket you are testing with?

Thanks!

@p5pRT
Copy link
Author

p5pRT commented Mar 4, 2011

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Mar 5, 2011

From quanah@zimbra.com

--On Wednesday, March 02, 2011 3​:35 PM -0800 perlbug-followup@​perl.org
wrote​:

Greetings,

This message has been automatically generated in response to the
creation of a perl bug report regarding​:
"inet_aton in Socket.pm core module is broken".

Here is an example.

If /etc/hosts is ordered with IPv6 before IPv4, inet_aton fails to return
any data​:

zimbra@​zqa-064​:~/libexec$ ./qtest.pl
ldap​: Net​::LDAP=HASH(0x248bbb8)
host​: zqa-064.eng.vmware.com​:389
arg​: HASH(0x21898d0)
Host adjusted to​: zqa-064.eng.vmware.com
Port adjusted to​: 389
Creating socket
IO​::Socket​::INET Address​:
IO​::Socket​::INET Address​: zqa-064.eng.vmware.com
IO​::Socket​::Inet addr_str​: zqa-064.eng.vmware.com
IO​::Socket​::INET h​:
IO​::Socket​::INET​: connect​: Connection refused at ./qtest.pl line 44, <DATA>
line 522.

"IO​::Socket​::INET h​:" is the value of inet_aton.

Example /etc/hosts used here​:

127.0.0.1 localhost

# The following lines are desirable for IPv6 capable hosts
#​::1 zqa-064.eng.vmware.com zqa-064 localhost ip6-localhost
ip6-loopback
:​:1 localhost ip6-localhost ip6-loopback zqa-064.eng.vmware.com
zqa-064
fe00​::0 ip6-localnet
ff00​::0 ip6-mcastprefix
ff02​::1 ip6-allnodes zqa-064.eng.vmware.com zqa-064
ff02​::2 ip6-allrouters

10.137.245.250 w1-zbuild-ns120-01-qa-nfs.eng.vmware.com
w1-zbuild-ns120-01-qa-nfs
10.137.244.64 zqa-064.eng.vmware.com zqa-064

Even modifying it thusly doesn't change the behavior​:

# The following lines are desirable for IPv6 capable hosts
#​::1 zqa-064.eng.vmware.com zqa-064 localhost ip6-localhost
ip6-loopback
:​:1 localhost ip6-localhost ip6-loopback
zqa-064.eng.vmware.com zqa-064
fe00​::0 ip6-localnet
ff00​::0 ip6-mcastprefix
ff02​::1 ip6-allnodes zqa-064.eng.vmware.com zqa-064
ff02​::2 ip6-allrouters

127.0.0.1 localhost

10.137.245.250 w1-zbuild-ns120-01-qa-nfs.eng.vmware.com
w1-zbuild-ns120-01-qa-nfs
10.137.244.64 zqa-064.eng.vmware.com zqa-064

Now, if I move the IPv4 addresses to be before the IPv6 configuration,
things work​:

zimbra@​zqa-064​:~/libexec$ ./qtest.pl
ldap​: Net​::LDAP=HASH(0x1f13bb8)
host​: zqa-064.eng.vmware.com​:389
arg​: HASH(0x1c118d0)
Host adjusted to​: zqa-064.eng.vmware.com
Port adjusted to​: 389
Creating socket
IO​::Socket​::INET Address​:
IO​::Socket​::INET Address​: zqa-064.eng.vmware.com
IO​::Socket​::Inet addr_str​: zqa-064.eng.vmware.com
IO​::Socket​::INET h​:
??@​
Leaving function

Here is /etc/hosts for this run​:

127.0.0.1 localhost

10.137.245.250 w1-zbuild-ns120-01-qa-nfs.eng.vmware.com
w1-zbuild-ns120-01-qa-nfs
10.137.244.64 zqa-064.eng.vmware.com zqa-064

# The following lines are desirable for IPv6 capable hosts
#​::1 zqa-064.eng.vmware.com zqa-064 localhost ip6-localhost
ip6-loopback
:​:1 localhost ip6-localhost ip6-loopback
zqa-064.eng.vmware.com zqa-064
fe00​::0 ip6-localnet
ff00​::0 ip6-mcastprefix
ff02​::1 ip6-allnodes zqa-064.eng.vmware.com zqa-064
ff02​::2 ip6-allrouters

It basically seems that Perl's inet_aton stops parsing /etc/hosts for IPv4
addresses as soon as it encounters its first IPv6 address definition, which
would be bug.

--Quanah

--

Quanah Gibson-Mount
Sr. Member of Technical Staff
Zimbra, Inc
A Division of VMware, Inc.


Zimbra :​: the leader in open source messaging and collaboration

@p5pRT
Copy link
Author

p5pRT commented Mar 5, 2011

From quanah@zimbra.com

--On Friday, March 04, 2011 11​:37 AM -0800 Steve Peters via RT
<perlbug-followup@​perl.org> wrote​:

Can you provide some sample code along with what operating system this
is along with the versions of Perl and Socket you are testing with?

I discovered the issue while using Net​::LDAP. Here is a brief set of
example code​:

#!/usr/bin/perl
use strict;
use lib "/opt/zimbra/zimbramon/lib";
use Net​::LDAP;
use MIME​::Base64;

my $ldap_master_url="ldap​://zqa-064.eng.vmware.com​:389";

my $ldap = Net​::LDAP->new("$ldap_master_url") or die "$@​";

$ldap->unbind();

Net​::LDAP makes a call to IO​::Socket​::INET, which in turn calls inet_aton.

I made the following modifications to IO​::Socket​::INET to see what was
happening with the inet_aton call​:

root@​zqa-064​:/opt/zimbra/zimbramon/lib/x86_64-linux-gnu-thread-multi/IO/Socket#

Inline Patch
diff -u INET.pm.orig INET.pm
--- INET.pm.orig        2011-03-01 13:07:51.970458204 -1000
+++ INET.pm     2011-03-01 13:10:37.430467992 -1000
@@ -77,6 +77,8 @@
   $port = $1
        if(defined $addr && $addr =~ s,:([\w\(\)/]+)$,,);

+  print "IO::Socket::INET Address: $addr\n";
+
   if(defined $proto  && $proto =~ /\D/) {
     my $num = _get_proto_number($proto);
     unless (defined $num) {
@@ -127,9 +129,12 @@
     my @addr;
     if ($multi && $addr_str !~ /^\d+(?:\.\d+){3}$/) {
        (undef, undef, undef, undef, @addr) = gethostbyname($addr_str);
+        print "IO::Socket::Inet addr_str: $addr_str\n";
     } else {
+        print "IO::Socket::Inet addr_str: $addr_str\n";
        my $h = inet_aton($addr_str);
        push(@addr, $h) if defined $h;
+        print "IO::Socket::INET h: $h\n";
     }
     @addr;
 }



Perl version is: root@​zqa\-064​:\~\# perl \-v

This is perl, v5.10.1 (*) built for x86_64-linux-gnu-thread-multi

The version of Socket shipped with it is $VERSION = "1.82";

This is on Ubuntu 10.04 LTS 64-bit

--Quanah

--

Quanah Gibson-Mount
Sr. Member of Technical Staff
Zimbra, Inc
A Division of VMware, Inc.


Zimbra :​: the leader in open source messaging and collaboration

@p5pRT
Copy link
Author

p5pRT commented Mar 5, 2011

From @smpeters

On Fri, Mar 4, 2011 at 2​:43 PM, Quanah Gibson-Mount <quanah@​zimbra.com>wrote​:

--On Friday, March 04, 2011 11​:37 AM -0800 Steve Peters via RT <
perlbug-followup@​perl.org> wrote​:

Can you provide some sample code along with what operating system this

is along with the versions of Perl and Socket you are testing with?

I discovered the issue while using Net​::LDAP. Here is a brief set of
example code​:

#!/usr/bin/perl
use strict;
use lib "/opt/zimbra/zimbramon/lib";
use Net​::LDAP;
use MIME​::Base64;

my $ldap_master_url="ldap​://zqa-064.eng.vmware.com​:389";

my $ldap = Net​::LDAP->new("$ldap_master_url") or die "$@​";

$ldap->unbind();

Net​::LDAP makes a call to IO​::Socket​::INET, which in turn calls inet_aton.

I made the following modifications to IO​::Socket​::INET to see what was
happening with the inet_aton call​:

root@​zqa-064​:/opt/zimbra/zimbramon/lib/x86_64-linux-gnu-thread-multi/IO/Socket#
diff -u INET.pm.orig INET.pm
--- INET.pm.orig 2011-03-01 13​:07​:51.970458204 -1000
+++ INET.pm 2011-03-01 13​:10​:37.430467992 -1000
@​@​ -77,6 +77,8 @​@​
$port = $1
if(defined $addr && $addr =~ s,​:([\w\(\)/]+)$,,);

+ print "IO​::Socket​::INET Address​: $addr\n";
+
if(defined $proto && $proto =~ /\D/) {
my $num = _get_proto_number($proto);
unless (defined $num) {
@​@​ -127,9 +129,12 @​@​
my @​addr;
if ($multi && $addr_str !~ /^\d+(?​:\.\d+){3}$/) {
(undef, undef, undef, undef, @​addr) = gethostbyname($addr_str);
+ print "IO​::Socket​::Inet addr_str​: $addr_str\n";
} else {
+ print "IO​::Socket​::Inet addr_str​: $addr_str\n";
my $h = inet_aton($addr_str);
push(@​addr, $h) if defined $h;
+ print "IO​::Socket​::INET h​: $h\n";
}
@​addr;
}

Perl version is​:
root@​zqa-064​:~# perl -v

This is perl, v5.10.1 (*) built for x86_64-linux-gnu-thread-multi

The version of Socket shipped with it is $VERSION = "1.82";

This is on Ubuntu 10.04 LTS 64-bit

The simple answer is that inet_aton() on a libc level does not handle IPv6
addresses, so the versions of the IO lib won't do what you want them to do.

Onto the fun part... We are obviously still using inet_aton() in
IO​::Socket​::INET, so it is obviously not compatible with an IPv6 world.

Steve Peters
steve@​fisharerojo.org

@p5pRT
Copy link
Author

p5pRT commented Mar 5, 2011

From quanah@zimbra.com

--On Friday, March 04, 2011 11​:57 PM -0600 Steve Peters
<steve@​fisharerojo.org> wrote​:

The simple answer is that inet_aton() on a libc level does not handle
IPv6 addresses, so the versions of the IO lib won't do what you want them
to do. 

Onto the fun part... We are obviously still using inet_aton() in
IO​::Socket​::INET, so it is obviously not compatible with an IPv6 world.

Well, there is IO​::Socket​::INET6, which works great with IPv4 and IPv6.
Unfortunately, there are many, many modules that don't utilize it.

And, as I noted, it is valid to define the IPv4 addresses after the IPv6
ones. There is no RFC I can find saying that the IPv4 configuration must
be defined prior to the IPv6 one. So it seems to me there is a breakage in
inet_aton() somewhere in that it does not fully parse /etc/hosts to get the
IPv4 address. I'm not stopping or restarting the ldap server... just
reordering the hosts file. Everything is still open on both IPv4 and IPv6.
:/

--Quanah

--

Quanah Gibson-Mount
Sr. Member of Technical Staff
Zimbra, Inc
A Division of VMware, Inc.


Zimbra :​: the leader in open source messaging and collaboration

@p5pRT
Copy link
Author

p5pRT commented Mar 6, 2011

From @nwc10

On Fri, Mar 04, 2011 at 10​:42​:28PM -0800, Quanah Gibson-Mount wrote​:

--On Friday, March 04, 2011 11​:57 PM -0600 Steve Peters
<steve@​fisharerojo.org> wrote​:

The simple answer is that inet_aton() on a libc level does not handle
IPv6 addresses, so the versions of the IO lib won't do what you want them
to do. 

Onto the fun part... We are obviously still using inet_aton() in
IO​::Socket​::INET, so it is obviously not compatible with an IPv6 world.

That's not quite correct, given that Socket​::inet_aton() isn't actually a pure
wrapper on the C library's inet_aton(). The C library's inet_aton() only deals
with dotted quad addresses. Socket​::inet_aton() helpfully (or is that
"helpfully") also deals with hostnames, by calling gethostbyname(). Like this​:

void
inet_aton(host)
  char * host
  CODE​:
  {
  struct in_addr ip_address;
  struct hostent * phe;

  if ((*host != '\0') && inet_aton(host, &ip_address)) {
  ST(0) = newSVpvn_flags((char *)&ip_address, sizeof ip_address, SVs_TEMP);
  XSRETURN(1);
  }

  phe = gethostbyname(host);
  if (phe && phe->h_addrtype == AF_INET && phe->h_length == 4) {
  ST(0) = newSVpvn_flags((char *)phe->h_addr, phe->h_length, SVs_TEMP);
  XSRETURN(1);
  }

  XSRETURN_UNDEF;
  }

And, as I noted, it is valid to define the IPv4 addresses after the IPv6
ones. There is no RFC I can find saying that the IPv4 configuration must
be defined prior to the IPv6 one. So it seems to me there is a breakage in
inet_aton() somewhere in that it does not fully parse /etc/hosts to get the
IPv4 address. I'm not stopping or restarting the ldap server... just
reordering the hosts file. Everything is still open on both IPv4 and IPv6.
:/

So I think that this is actually a bug in the OS gethostbyname()
implementation, as it is being passed the hostname string, and returning
failure.

However, I'm hoping that it can be worked round with something like this​:

From f0a6093 Mon Sep 17 00​:00​:00 2001
From​: Nicholas Clark <nick@​ccl4.org>
Date​: Sun, 6 Mar 2011 11​:04​:52 +0000
Subject​: [PATCH] Socket​::inet_aton() should fall back to getaddinfo() if gethostbyname() fails.

This is a last resort, in case gethostbyname() is getting confused because it
only looks at the first result that it gets from its upstream, and that is not
AF_INET. The assumption is that in this case, getaddrinfo() will be well
written.


ext/Socket/Socket.xs | 20 +++++++++++++++++++-
1 files changed, 19 insertions(+), 1 deletions(-)

Inline Patch
diff --git a/ext/Socket/Socket.xs b/ext/Socket/Socket.xs
index 9214fc1..71f0c57 100644
--- a/ext/Socket/Socket.xs
+++ b/ext/Socket/Socket.xs
@@ -435,7 +435,25 @@ inet_aton(host)
 		XSRETURN(1);
 	}
 
-	XSRETURN_UNDEF;
+	ST(0) = &PL_sv_undef;
+#ifdef HAS_GETADDRINFO
+	{
+		struct addrinfo hints = { 0 };
+		struct addrinfo *result;
+
+		hints.ai_family = AF_INET;
+		if (!getaddrinfo(host, NULL, &hints, &result) && result) {
+			/* These two checks are just paranoia.  */
+			if (result->ai_family == AF_INET && result->ai_addr->sa_family == AF_INET) {
+				ST(0) = newSVpvn_flags((char *)&((const struct sockaddr_in *)result->ai_addr)->sin_addr,
+						       sizeof(ip_address), SVs_TEMP);
+			}
+			freeaddrinfo(result);
+		}
+	}
+#endif
+
+	XSRETURN(1);
 	}
 
 void
-- 
1.6.0

I can't test that for sure, as I've not found a machine where I can replicate
this. (ie one where I have root access and it's safe for me to mess with
/etc/hosts). The code above does work, in that I forced it to be called by
commenting out the gethostbyname() call immediately above, and it returned the
same 4 byte addresses. However, it's the first time I've ever used
getaddrinfo(), so I don't know if I made some stupid mistakes. Or whether my
paranoia is too much (or too little - can hints be ignored? Should it iterate
over all results?)

That patch, as inlined, isn't going to apply to 5.10.1's Socket.xs, or even
5.13.01's, as it builds on two commits I just made to refactor inet_aton's
layout (to that shown above). Splicing in the new code to 5.10.1's Socket.xs
isn't going to work (trivially), as its Configure script doesn't probe for
getaddrinfo, so HAS_GETADDRINFO is never defined. For testing, I guess,
just remove the #ifdef.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Mar 7, 2011

From @nwc10

On Mon, Mar 07, 2011 at 02​:09​:26PM -0800, Quanah Gibson-Mount wrote​:

[hmm, I had hoped that that would work]

Maybe I should be bothering the core linux devs instead?

I think if you can get rewrite the test as a single standalone file of C, and
its behaviour varies depending on the order of the lines in /etc/hosts, it's
fair game to report it as a bug in glibc.

If the C code works, whereas the XS version doesn't, then we need to scratch
our heads harder about what is actually going on, and where the bug lies.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Mar 8, 2011

From quanah@zimbra.com

--On Sunday, March 06, 2011 11​:35 AM +0000 Nicholas Clark <nick@​ccl4.org>
wrote​:

That's not quite correct, given that Socket​::inet_aton() isn't actually a
pure wrapper on the C library's inet_aton(). The C library's inet_aton()
only deals with dotted quad addresses. Socket​::inet_aton() helpfully (or
is that "helpfully") also deals with hostnames, by calling
gethostbyname(). Like this​:

That patch, as inlined, isn't going to apply to 5.10.1's Socket.xs, or
even 5.13.01's, as it builds on two commits I just made to refactor
inet_aton's layout (to that shown above). Splicing in the new code to
5.10.1's Socket.xs isn't going to work (trivially), as its Configure
script doesn't probe for getaddrinfo, so HAS_GETADDRINFO is never
defined. For testing, I guess, just remove the #ifdef.

I downloaded the 5.10.1 Socket code, and modified Socket.xs thusly​:

root@​zqa-064​:/tmp/q# diff -u Socket.xs.orig Socket.xs

Inline Patch
--- Socket.xs.orig      2011-03-07 11:59:03.640485053 -1000
+++ Socket.xs   2011-03-07 12:00:13.840461063 -1000
@@ -231,17 +231,34 @@
        {
        struct in_addr ip_address;
        struct hostent * phe;
-       int ok = (*host != '\0') && inet_aton(host, &ip_address);

-       if (!ok && (phe = gethostbyname(host)) &&
-                       phe->h_addrtype == AF_INET && phe->h_length == 4) {
-               Copy( phe->h_addr, &ip_address, phe->h_length, char );
-               ok = 1;
+       if ((*host != '\0') && inet_aton(host, &ip_address)) {
+               ST(0) = newSVpvn_flags((char *)&ip_address, sizeof 
ip_address, SVs_TEMP); \+ XSRETURN\(1\);   \}

- ST(0) = sv_newmortal();
- if (ok)
- sv_setpvn( ST(0), (char *)&ip_address, sizeof ip_address );
+ phe = gethostbyname(host);
+ if (phe && phe->h_addrtype == AF_INET && phe->h_length == 4) {
+ ST(0) = newSVpvn_flags((char *)phe->h_addr, phe->h_length,
SVs_TEMP);
+ XSRETURN(1);
+ }
+ ST(0) = &PL_sv_undef;
+ {
+ struct addrinfo hints = { 0 };
+ struct addrinfo *result;
+
+ hints.ai_family = AF_INET;
+ if (!getaddrinfo(host, NULL, &hints, &result) && result) {
+ /* These two checks are just paranoia. */
+ if (result->ai_family == AF_INET &&
result->ai_addr->sa_family == AF_INET) {
+ ST(0) = newSVpvn_flags((char *)&((const
struct sockaddr_in *)result->ai_addr)->sin_addr,
+ sizeof(ip_address),
SVs_TEMP);
+ }
+ freeaddrinfo(result);
+ }
+ }
+
+ XSRETURN(1);
  }

void

I then rebuilt Socket, installing it into a different location
(/opt/zimbra/zimbramon/lib) where we store our self-built perl modules.

I then moved the system socket aside (renamed Socket.pm and Socket.xs in
/usr/lib/perl/5.10.1 so they wouldn't get loaded).

Still fails​:

zimbra@​zqa-064​:~/libexec$ ./qtest.pl
ldap​: Net​::LDAP=HASH(0x2539d48)
host​: zqa-064.eng.vmware.com​:389
arg​: HASH(0x26fc260)
Host adjusted to​: zqa-064.eng.vmware.com
Port adjusted to​: 389
Creating socket
IO​::Socket​::INET Address​:
IO​::Socket​::INET Address​: zqa-064.eng.vmware.com
IO​::Socket​::Inet addr_str​: zqa-064.eng.vmware.com
IO​::Socket​::INET h​:
IO​::Socket​::INET​: connect​: Connection refused at ./qtest.pl line 9, <DATA>
line 522.

Maybe I should be bothering the core linux devs instead?

--Quanah

--

Quanah Gibson-Mount
Sr. Member of Technical Staff
Zimbra, Inc
A Division of VMware, Inc.


Zimbra :​: the leader in open source messaging and collaboration

@p5pRT
Copy link
Author

p5pRT commented Mar 8, 2011

From quanah@zimbra.com

--On Monday, March 07, 2011 10​:15 PM +0000 Nicholas Clark <nick@​ccl4.org>
wrote​:

On Mon, Mar 07, 2011 at 02​:09​:26PM -0800, Quanah Gibson-Mount wrote​:

[hmm, I had hoped that that would work]

Maybe I should be bothering the core linux devs instead?

I think if you can get rewrite the test as a single standalone file of C,
and its behaviour varies depending on the order of the lines in
/etc/hosts, it's fair game to report it as a bug in glibc.

If the C code works, whereas the XS version doesn't, then we need to
scratch our heads harder about what is actually going on, and where the
bug lies.

root@​zqa-064​:~# ./a.out zqa-064.eng.vmware.com
Host​: zqa-064.eng.vmware.com
IPv6 address​: :​:1 (localhost)
IPv4 address​: 10.137.244.64 ((null))
IPv6 address​: ff02​::1 ((null))

So it correctly gets the IPv6 and IPv4 addresses, although it doesn't have
the hostname correctly associated.

I used <http​://www.logix.cz/michal/devel/various/getaddrinfo.c.xp> for the
code.

--Quanah

--

Quanah Gibson-Mount
Sr. Member of Technical Staff
Zimbra, Inc
A Division of VMware, Inc.


Zimbra :​: the leader in open source messaging and collaboration

@p5pRT
Copy link
Author

p5pRT commented Mar 8, 2011

From @ikegami

On Sun, Mar 6, 2011 at 6​:35 AM, Nicholas Clark <nick@​ccl4.org> wrote​:

So I think that this is actually a bug in the OS gethostbyname()
implementation, as it is being passed the hostname string, and returning
failure.

Or its returning an IPv6 address? Maybe it would be more appropriate to use
gethostbyname2 instead?

struct hostent * gethostbyname(const char *name);
struct hostent * gethostbyname2(const char *name, int af);

@p5pRT
Copy link
Author

p5pRT commented Mar 8, 2011

From @nwc10

On Wed Mar 02 15​:35​:49 2011, quanah@​zimbra.com wrote​:

This is a bug report for perl from quanah@​zimbra.com,
generated with the help of perlbug 1.39 running under perl 5.10.1.

[Please do not change anything below this line]

Locally applied patches​:

---
@​INC for perl 5.10.1​:

I'm curious. How many lines of "locally applied patches" did you edit
out? The slightly newer version of Perl 5.10.1 on an Ubuntu desktop here
has 40 lines detailing locally applied patches.

I don't think that it makes a difference to the problem, as Debian
doesn't tend to do anything insane to perl, but we'd prefer it if the
instruction about "please do not change anything below this line" were
followed.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Mar 8, 2011

From @nwc10

On Mon, Mar 07, 2011 at 02​:09​:26PM -0800, Quanah Gibson-Mount wrote​:

I then rebuilt Socket, installing it into a different location
(/opt/zimbra/zimbramon/lib) where we store our self-built perl modules.

I then moved the system socket aside (renamed Socket.pm and Socket.xs in
/usr/lib/perl/5.10.1 so they wouldn't get loaded).

You typed Socket.xs
Did you mean Socket.so?

What matters at load time is the shared object (which on Linux is a .so,
likely /usr/lib/perl/5.10.1/auto/Socket/Socket.so )

If you didn't move that, then I think that *it* will still be loaded, and
there won't be any behaviour change.

On Mon, Mar 07, 2011 at 02​:45​:50PM -0800, Quanah Gibson-Mount wrote​:

--On Monday, March 07, 2011 10​:15 PM +0000 Nicholas Clark <nick@​ccl4.org>
wrote​:

On Mon, Mar 07, 2011 at 02​:09​:26PM -0800, Quanah Gibson-Mount wrote​:

[hmm, I had hoped that that would work]

Maybe I should be bothering the core linux devs instead?

I think if you can get rewrite the test as a single standalone file of C,
and its behaviour varies depending on the order of the lines in
/etc/hosts, it's fair game to report it as a bug in glibc.

If the C code works, whereas the XS version doesn't, then we need to
scratch our heads harder about what is actually going on, and where the
bug lies.

root@​zqa-064​:~# ./a.out zqa-064.eng.vmware.com
Host​: zqa-064.eng.vmware.com
IPv6 address​: :​:1 (localhost)
IPv4 address​: 10.137.244.64 ((null))
IPv6 address​: ff02​::1 ((null))

So it correctly gets the IPv6 and IPv4 addresses, although it doesn't have
the hostname correctly associated.

I used <http​://www.logix.cz/michal/devel/various/getaddrinfo.c.xp> for the
code.

If I compile that code on an Ubuntu box, and use your first /etc/hosts, I
see this​:

$ ./getaddrinfo zqa-064.eng.vmware.com
Host​: zqa-064.eng.vmware.com
IPv6 address​: :​:1 (localhost)
IPv4 address​: 10.137.244.64 ((null))
IPv6 address​: ff02​::1 ((null))

If I change it to pass AF_INET in the hints to getaddrinfo(), and also make it
call gethostbyname() [attached], I see this​:

$ ./85308 zqa-064.eng.vmware.com
Host​: zqa-064.eng.vmware.com
IPv4 address​: 127.0.0.1 (localhost)
IPv4 address​: 10.137.244.64 ((null))
gethostbyname
IPv4 address​: 127.0.0.1 (localhost)
IPv4 address​: 10.137.244.64 (localhost)

Please could you compile the attached variant, and run it? I'm not sure what
output to expect.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Mar 8, 2011

From @nwc10

/* 
 * getaddrinfo.c - Simple example of using getaddrinfo(3) function.
 * 
 * Michal Ludvig <michal@logix.cz> (c) 2002, 2003
 * http://www.logix.cz/michal/devel/
 *
 * License: public domain.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int
lookup_host (const char *host)
{
  struct addrinfo hints, *res;
  int errcode;
  char addrstr[100];
  void *ptr;

  memset (&hints, 0, sizeof (hints));
  hints.ai_family = PF_INET;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags |= AI_CANONNAME;

  errcode = getaddrinfo (host, NULL, &hints, &res);
  if (errcode != 0)
    {
      perror ("getaddrinfo");
      return -1;
    }

  printf ("Host: %s\n", host);
  while (res)
    {
      inet_ntop (res->ai_family, res->ai_addr->sa_data, addrstr, 100);

      switch (res->ai_family)
        {
        case AF_INET:
          ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr;
          break;
        case AF_INET6:
          ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
          break;
        }
      inet_ntop (res->ai_family, ptr, addrstr, 100);
      printf ("IPv%d address: %s (%s)\n", res->ai_family == PF_INET6 ? 6 : 4,
              addrstr, res->ai_canonname);
      res = res->ai_next;
    }

  {
    struct hostent * phe = gethostbyname(host);
    char **addr;

    puts("gethostbyname");
    if (!phe) {
      perror ("gethostbyname");
      return -1;
    }

    addr = phe->h_addr_list;

    while (*addr) {
      inet_ntop (phe->h_addrtype, *addr, addrstr, 100);
      printf ("IPv%d address: %s (%s)\n", phe->h_addrtype == AF_INET6 ? 6 : 4,
	      addrstr, phe->h_name);
      ++addr;
    }
  }

  return 0;
}

int
main (int argc, char *argv[])
{
  if (argc < 2)
    exit (1);
  return lookup_host (argv[1]);
}

@p5pRT
Copy link
Author

p5pRT commented Mar 9, 2011

From quanah@zimbra.com

--On March 8, 2011 12​:51​:08 PM -0800 Nicholas Clark via RT
<perlbug-followup@​perl.org> wrote​:

On Wed Mar 02 15​:35​:49 2011, quanah@​zimbra.com wrote​:

This is a bug report for perl from quanah@​zimbra.com,
generated with the help of perlbug 1.39 running under perl 5.10.1.

[Please do not change anything below this line]

Locally applied patches​:

---
@​INC for perl 5.10.1​:

I'm curious. How many lines of "locally applied patches" did you edit
out? The slightly newer version of Perl 5.10.1 on an Ubuntu desktop here
has 40 lines detailing locally applied patches.

I don't think that it makes a difference to the problem, as Debian
doesn't tend to do anything insane to perl, but we'd prefer it if the
instruction about "please do not change anything below this line" were
followed.

I didn't edit any out. I sent the full report that came from perlbug. I
have no idea what patches Ubuntu/Debian uses, either.

--Quanah

--
Quanah Gibson-Mount
Principal Software Engineer
Zimbra, Inc


Zimbra :​: the leader in open source messaging and collaboration

@p5pRT
Copy link
Author

p5pRT commented Mar 9, 2011

From quanah@zimbra.com

--On March 8, 2011 9​:38​:02 PM +0000 Nicholas Clark <nick@​ccl4.org> wrote​:

On Mon, Mar 07, 2011 at 02​:09​:26PM -0800, Quanah Gibson-Mount wrote​:

I then rebuilt Socket, installing it into a different location
(/opt/zimbra/zimbramon/lib) where we store our self-built perl modules.

I then moved the system socket aside (renamed Socket.pm and Socket.xs in
/usr/lib/perl/5.10.1 so they wouldn't get loaded).

You typed Socket.xs
Did you mean Socket.so?

Yes, Socket.so, sorry.

What matters at load time is the shared object (which on Linux is a .so,
likely /usr/lib/perl/5.10.1/auto/Socket/Socket.so )

Yes, I'm quite aware of that. ;)

If you didn't move that, then I think that *it* will still be loaded, and
there won't be any behaviour change.

It is what was moved, to explicitly avoid it being loaded.

I will build the attached variant and let you know how it goes.

--Quanah

--
Quanah Gibson-Mount
Principal Software Engineer
Zimbra, Inc


Zimbra :​: the leader in open source messaging and collaboration

@p5pRT
Copy link
Author

p5pRT commented Mar 9, 2011

From @ntyni

On Tue, Mar 08, 2011 at 12​:51​:08PM -0800, Nicholas Clark via RT wrote​:

On Wed Mar 02 15​:35​:49 2011, quanah@​zimbra.com wrote​:

This is a bug report for perl from quanah@​zimbra.com,
generated with the help of perlbug 1.39 running under perl 5.10.1.

[Please do not change anything below this line]

Locally applied patches​:

---
@​INC for perl 5.10.1​:

I'm curious. How many lines of "locally applied patches" did you edit
out? The slightly newer version of Perl 5.10.1 on an Ubuntu desktop here
has 40 lines detailing locally applied patches.

I only added proper patchlevel.h handling a year ago in Debian package
version 5.10.1-10. Older versions have an empty list of locally applied
patches.

It looks like at least one supported Ubuntu version ("Lucid Lynx") has
a 5.10.1 perl package that is based on an earlier Debian package version
(5.10.1-8), so that probably explains the difference.
--
Niko Tyni ntyni@​debian.org

@p5pRT
Copy link
Author

p5pRT commented Mar 10, 2011

From quanah@zimbra.com

--On March 8, 2011 9​:38​:02 PM +0000 Nicholas Clark <nick@​ccl4.org> wrote​:

If I compile that code on an Ubuntu box, and use your first /etc/hosts, I
see this​:

$ ./getaddrinfo zqa-064.eng.vmware.com
Host​: zqa-064.eng.vmware.com
IPv6 address​: :​:1 (localhost)
IPv4 address​: 10.137.244.64 ((null))
IPv6 address​: ff02​::1 ((null))

If I change it to pass AF_INET in the hints to getaddrinfo(), and also
make it call gethostbyname() [attached], I see this​:

$ ./85308 zqa-064.eng.vmware.com
Host​: zqa-064.eng.vmware.com
IPv4 address​: 127.0.0.1 (localhost)
IPv4 address​: 10.137.244.64 ((null))
gethostbyname
IPv4 address​: 127.0.0.1 (localhost)
IPv4 address​: 10.137.244.64 (localhost)

Please could you compile the attached variant, and run it? I'm not sure
what output to expect.

root@​zqa-064​:~# ./inettest2 zqa-064.eng.vmware.com
Host​: zqa-064.eng.vmware.com
IPv4 address​: 127.0.0.1 (localhost)
IPv4 address​: 10.137.244.64 ((null))
gethostbyname
IPv4 address​: 127.0.0.1 (localhost)
IPv4 address​: 10.137.244.64 (localhost)

--Quanah

--
Quanah Gibson-Mount
Principal Software Engineer
Zimbra, Inc


Zimbra :​: the leader in open source messaging and collaboration

@p5pRT
Copy link
Author

p5pRT commented May 14, 2015

From @jmcabandara

Operations logged to /tmp/install.log.22392
Checking for existing installation...
  zimbra-ldap...FOUND zimbra-ldap-8.6.0_GA_1153
  zimbra-logger...FOUND zimbra-logger-8.6.0_GA_1153
  zimbra-mta...FOUND zimbra-mta-8.6.0_GA_1153
  zimbra-dnscache...NOT FOUND
  zimbra-snmp...FOUND zimbra-snmp-8.6.0_GA_1153
  zimbra-store...FOUND zimbra-store-8.6.0_GA_1153
  zimbra-apache...FOUND zimbra-apache-8.6.0_GA_1153
  zimbra-spell...FOUND zimbra-spell-8.6.0_GA_1153
  zimbra-convertd...NOT FOUND
  zimbra-memcached...FOUND zimbra-memcached-8.6.0_GA_1153
  zimbra-proxy...FOUND zimbra-proxy-8.6.0_GA_1153
  zimbra-archiving...NOT FOUND
  zimbra-core...FOUND zimbra-core-8.6.0_GA_1153
ZCS upgrade from 8.6.0 to 8.6.0 will be performed.
Validating ldap configuration
Can't load '/opt/zimbra/zimbramon/lib/x86_64-linux-thread-multi/auto/Socket/Socket.so' for module Socket​: /lib64/libc.so.6​: version `GLIBC_2.14' not found (required by /opt/zimbra/zimbramon/lib/x86_64-linux-thread-multi/auto/Socket/Socket.so) at /usr/lib64/perl5/XSLoader.pm line 70.
at /opt/zimbra/zimbramon/lib/x86_64-linux-thread-multi/Socket.pm line 858.
Compilation failed in require at /opt/zimbra/zimbramon/lib/Net/LDAP.pm line 8.
BEGIN failed--compilation aborted at /opt/zimbra/zimbramon/lib/Net/LDAP.pm line 8.
Compilation failed in require at bin/zmValidateLdap.pl line 23.
BEGIN failed--compilation aborted at bin/zmValidateLdap.pl line 23.
Error​: Unable to bind to the LDAP server as the root LDAP user.
  This is required to upgrade.

@p5pRT
Copy link
Author

p5pRT commented May 14, 2015

From [Unknown Contact. See original ticket]

Operations logged to /tmp/install.log.22392
Checking for existing installation...
  zimbra-ldap...FOUND zimbra-ldap-8.6.0_GA_1153
  zimbra-logger...FOUND zimbra-logger-8.6.0_GA_1153
  zimbra-mta...FOUND zimbra-mta-8.6.0_GA_1153
  zimbra-dnscache...NOT FOUND
  zimbra-snmp...FOUND zimbra-snmp-8.6.0_GA_1153
  zimbra-store...FOUND zimbra-store-8.6.0_GA_1153
  zimbra-apache...FOUND zimbra-apache-8.6.0_GA_1153
  zimbra-spell...FOUND zimbra-spell-8.6.0_GA_1153
  zimbra-convertd...NOT FOUND
  zimbra-memcached...FOUND zimbra-memcached-8.6.0_GA_1153
  zimbra-proxy...FOUND zimbra-proxy-8.6.0_GA_1153
  zimbra-archiving...NOT FOUND
  zimbra-core...FOUND zimbra-core-8.6.0_GA_1153
ZCS upgrade from 8.6.0 to 8.6.0 will be performed.
Validating ldap configuration
Can't load '/opt/zimbra/zimbramon/lib/x86_64-linux-thread-multi/auto/Socket/Socket.so' for module Socket​: /lib64/libc.so.6​: version `GLIBC_2.14' not found (required by /opt/zimbra/zimbramon/lib/x86_64-linux-thread-multi/auto/Socket/Socket.so) at /usr/lib64/perl5/XSLoader.pm line 70.
at /opt/zimbra/zimbramon/lib/x86_64-linux-thread-multi/Socket.pm line 858.
Compilation failed in require at /opt/zimbra/zimbramon/lib/Net/LDAP.pm line 8.
BEGIN failed--compilation aborted at /opt/zimbra/zimbramon/lib/Net/LDAP.pm line 8.
Compilation failed in require at bin/zmValidateLdap.pl line 23.
BEGIN failed--compilation aborted at bin/zmValidateLdap.pl line 23.
Error​: Unable to bind to the LDAP server as the root LDAP user.
  This is required to upgrade.

@p5pRT
Copy link
Author

p5pRT commented May 26, 2015

From @tonycoz

On Thu May 14 10​:06​:09 2015, jmcabandara@​gmail.com wrote​:

Operations logged to /tmp/install.log.22392
Checking for existing installation...
zimbra-ldap...FOUND zimbra-ldap-8.6.0_GA_1153
...
Can't load '/opt/zimbra/zimbramon/lib/x86_64-linux-thread-
multi/auto/Socket/Socket.so' for module Socket​: /lib64/libc.so.6​:
version `GLIBC_2.14' not found (required by
/opt/zimbra/zimbramon/lib/x86_64-linux-thread-
multi/auto/Socket/Socket.so) at /usr/lib64/perl5/XSLoader.pm line 70.
at /opt/zimbra/zimbramon/lib/x86_64-linux-thread-multi/Socket.pm line
858.
Compilation failed in require at /opt/zimbra/zimbramon/lib/Net/LDAP.pm
line 8.

This doesn't appear to have anything to do with the original problem in
this ticket.

Are you trying to report a new problem?

If you're having problems installing pre-built packages supplied by
an OS distribution you should probably take it up with the distributor.

Tony

@p5pRT
Copy link
Author

p5pRT commented May 26, 2015

From mishikal@yahoo.com

On Thu May 14 10​:06​:09 2015, jmcabandara@​gmail.com wrote​:

This indicates you installed a version of ZCS that doesn't match your operating system.

I.e., you installed a RHEL6 build on RHEL7, or an Ubuntu12 build on Ubuntu14, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants