Subject: | Spurrious "addr is not a string" error |
This problem caused me quite some headaches, but I understand if you
don't care...
On a system still running 5.8.8 / 2.6.17-1.2142_FC4 (and yes, it is
scheduled to upgrade, but...), I installed Socket 2.006 for some IPV6
work.
A small chunk of code calls getnameinfo with the output of getaddrinfo.
It works standalone, but fails under apache httpd. The very same
inputs. This is quite strange.
In Socket.xs, we have:
if(!SvPOK(addr))
croak("addr is not a string");
I have no clue why we hit this croak. I put a fair bit of diagnostic
code into the xs, and tested for refs, arrays, hashs - in fact
everything. addr wasn't any of those. I dumped addr from the perl
side and verified that yes, what was being passed is in fact a valid
adddress string. I tried various things: passing the string in a
scalar, introducing a subroutine. Nothing worked. BUT, remember that
the same code works stand-alone...
Finally, I simply commented-out the test, and everything "works" - in
that the correct data is returned for a few hundred test cases.
I know 5.8.8 is old, but worry that the issue may appear under more
recent versions. I'm not an XS expert, but it has the feel of an
incorrect reference count or some such. So I thought I should report
it.
Here is the code. It is passed an IP address (V4 or V6) as a string.
It returns the corresponding host name, or an empty string.
The eval is only to catch this error (since Socket is supplying and
consuming the data, it "shouldn't happen".)
One other thing - what's supposed to happen with an address that has
multiple names? getnameinfo doesn't seem to suppor this.
gethostbyaddr did - and it's not uncommon for one address to have
multiple PTR records in IPV4...
Thanks.
#!/usr/bin/perl -d
use strict;
use warnings;
use Socket qw( :addrinfo inet_ntoa inet_aton SOCK_RAW PF_INET
PF_INET6 );
sub getHostFromAddr($) {
my $addr = shift;
my( $error, @addrs ) = getaddrinfo( $addr, 0, { flags =>
AI_NUMERICHOST } );
return '' if( $error );
my $name;
eval {
($error, $name, undef) = getnameinfo( $addrs[0]->{addr},
NI_NAMEREQD, NIx_NOSERV );
}; return '' if( $@ );
return '' if( $error );
return $name;
}
my $x = '192.168.148.108';
print getHostFromAddr($x);