是否可以在Perl中覆盖或修改gethostbyname以支持IPv6?
我给出了application which uses Perl's gethostbyname
to check if a hostname exists in DNS。我不想修补不是由我写的应用程序的源代码。但我想在Perl编写的配置文件之一中覆盖gethostbyname
。是否可以在Perl中覆盖或修改gethostbyname以支持IPv6?
所以我想知道是否有机会以某种方式猴子修补它。
的documentation of that application says that its hostname lookups work as follows:
$ perl -e 'print(gethostbyname("ipv6.google.com") ? "ok\n" : "not found\n");'
not found
到目前为止,我尝试:
$ perl -E 'use Socket qw(:DEFAULT getaddrinfo); sub gethostbyname { my ($err, @result) = getaddrinfo(@_); return @result; }; print(gethostbyname("ipv6.google.com") ? "ok\n" : "not found\n");'
not found
而且:
$ perl -E 'use Socket qw(:DEFAULT getaddrinfo); use Monkey::Patch::Action qw(patch_package); patch_package("*", "gethostbyname", "add", sub { my ($err, @result) = getaddrinfo(@_); return @result; }); print(gethostbyname("ipv6.google.com") ? "ok\n" : "not found\n");'
not found
(我也试过main
代替*
和replace
代替add
replace
跳伞如下:Replacing *::gethostbyname: must already exist at /usr/share/perl5/Monkey/Patch/Action.pm line 31.
)
TL; TR:那不是解释如何覆盖gethostbyname
(现有的意见应帮助这样做),而是解释说,这不能解决使这一特定代码的实际问题,支持IPv6 。
首先,IPv6准备gethostbyname
应该返回什么?使用IPv4时,它将返回一个打包的IPv4地址,代码gethostbyname
的预期值就是这样。此类代码通常会使用sockaddr_in
,PF_INET
套接字等。但对于IPv6,此代码需要使用和PF_INET6
,这意味着它不足以修补gethostbyname
。
而且,要进一步研究代码,您必须解决这个问题实际上就是这样。您只需将您的问题链接到gethostbyname
的电话,该电话只会检查是否返回定义的值。但是如果你看further in the code,你会看到明确使用inet_aton
,PF_INET
套接字等,即所有假定只有IPv4地址的东西。
感谢您的支持。我没有因为我很忙,但这就是为什么我发表评论,而不是回答:) – ikegami
感谢您深入挖掘。我确实认为它只是检查一个主机名是否解析,因此返回值的实际类型是不相关的。 –
在第二个片段中,你所需要的只是'use subs qw(gethostbyname);'。 – ikegami
在第三个片段中,我认为用'BEGIN'包装'patch_package'就可以了。 – ikegami
但是你可能想要从调用'gethostbyname'的模块外面打补丁(或者你只需要调用正确的sub)。你可以通过命名你的覆盖'CORE :: GLOBAL :: gethostbyname'(在使用'gethostbyname'的模块被加载之前)来做到这一点。请参阅[覆盖内置函数](https://perldoc.perl.org/perlsub.html#Overriding-Built-in-Functions)。您可以使用'caller'来仅提供覆盖选择模块。 – ikegami