File Coverage

blib/lib/Net/Server/Proto.pm
Criterion Covered Total %
statement 224 272 82.3
branch 122 194 62.8
condition 63 145 43.4
subroutine 25 27 92.5
pod 1 8 12.5
total 435 646 67.3


line stmt bran cond sub pod time code
1             # -*- perl -*-
2             #
3             # Net::Server::Proto - Net::Server Protocol compatibility layer
4             #
5             # Copyright (C) 2001-2026
6             #
7             # Paul Seamons
8             #
9             # Rob Brown
10             #
11             # This package may be distributed under the terms of either the
12             # GNU General Public License
13             # or the
14             # Perl Artistic License
15             #
16             # All rights reserved.
17             #
18             ################################################################
19              
20             package Net::Server::Proto;
21              
22 76     76   9547632 use strict;
  76         207  
  76         3693  
23 76     76   716 use warnings;
  76         198  
  76         5600  
24 76     76   551 use Carp qw(croak);
  76         269  
  76         6899  
25 76     76   1008 use Socket ();
  76         7746  
  76         2121  
26 76     76   389 use Exporter ();
  76         147  
  76         2551  
27 76     76   408 use constant NIx_NOHOST => 1; # The getNameInfo Xtended flags are too difficult to obtain on some older systems,
  76         140  
  76         7615  
28 76     76   565 use constant NIx_NOSERV => 2; # So just hard-code the constant numbers.
  76         149  
  76         27761  
29              
30             my $ipv6_package;
31             my $can_disable_v6only;
32             my $exported = {};
33             my $have6;
34             my $stub_wrapper;
35              
36             our @EXPORT;
37             our @EXPORT_OK; # Allow any routine defined in this module to be exported, except block these static methods:
38             our @EXPORT_DENIED = qw[
39             import
40             ];
41             sub IPV6_V6ONLY();
42              
43             sub import {
44 148     148   1021 my $class = shift;
45 148         861 my $callpkg = caller;
46 148         1018 foreach my $func (@_) {
47 1353 100       2838 if (!grep {$_ eq $func} @EXPORT_OK) { # Trying to import something not in my list
  34999         59972  
48 270 50       1172 croak "$func: Can't import underbar routine" if $func =~ /^_/;
49 270 50       1449 if (!exists &$func) { # Symbol doesn't exist here yet
50 0         0 grep {$_ eq $func} @Socket::EXPORT,@Socket::EXPORT_OK # Is exportable by Socket
51             or ($have6 || !defined $have6 && eval{($have6=0)=require Socket6}) && # Or else if Socket6 is available, AND
52 0 0 0     0 grep {$_ eq $func} @Socket6::EXPORT,@Socket6::EXPORT_OK # Is exportable by Socket6
  0   0     0  
      0        
53             or croak "$func is not a valid Socket macro nor defined by ".__PACKAGE__." and could not be imported";
54 76     76   529 no strict 'refs'; *$func = sub { $stub_wrapper->($func,@_) };
  76     0   243  
  76         33953  
  0         0  
  0         0  
55             }
56 270 50       841 croak "$func is a static method invoked via ".__PACKAGE__."->$func so it cannot be imported" if grep {$_ eq $func} @EXPORT_DENIED;
  270         806  
57 270         963 push @EXPORT_OK, $func; # Verified routine or stub exists, so it's safe to append to my exportable list
58             }
59             }
60             # Keep track of who imports any fake stub wrappers
61 148         4993 $exported->{$_}->{$callpkg}=1 foreach @_;
62 148         49277 return Exporter::export($class, $callpkg, @_);
63             }
64              
65             BEGIN {
66             # If the underlying constant or routine really isn't available in Socket nor Socket6,
67             # then it will not die until run-time instead of crashing at compile-time.
68             # It can still be caught with eval.
69 76     76   688 @EXPORT_OK = qw[
70             AF_INET
71             AF_INET6
72             AF_UNIX
73             AF_UNSPEC
74             AI_PASSIVE
75             INADDR_ANY
76             NI_NUMERICHOST
77             NI_NUMERICSERV
78             NIx_NOHOST
79             NIx_NOSERV
80             SOCK_DGRAM
81             SOCK_STREAM
82             SOMAXCONN
83             SOL_SOCKET
84             SO_TYPE
85             IPPROTO_IPV6
86             IPV6_V6ONLY
87             sockaddr_in
88             sockaddr_in6
89             sockaddr_family
90             inet_ntop
91             inet_ntoa
92             inet_aton
93             getaddrinfo
94             getnameinfo
95             ];
96              
97             # Load just in time once explicitly invoked.
98 76         185 my $sub = {};
99             $stub_wrapper = sub {
100 780         6505 my @c = caller 1;
101 780         3683 my $fullname = __PACKAGE__."::".(my $basename = shift);
102             # Manually run routine if import failed to brick over symbol in local namespace during the last attempt.
103 780 0       2310 $sub->{$fullname} ? (return $sub->{$fullname}->(@_)) : (die "$fullname: Unable to replace symbol") if exists $sub->{$fullname};
    50          
104             # Socket < 2.xxx and Socket6 can conjure constant routine on-the-fly via AUTOLOAD upon invocation, so "can" may not work until the second time.
105 76     76   649 no strict 'refs'; # Avoid Crash: Can't use string as a subroutine ref while "strict refs"
  76         153  
  76         15152  
106 780   33     8686 $sub->{$fullname} = Socket ->can($basename) || eval { &{"Socket ::$basename"};0} || Socket ->can($basename); # Always try Socket.pm first, then Socket6.pm
107             $sub->{$fullname}||= Socket6->can($basename) || eval { &{"Socket6::$basename"};0} || Socket6->can($basename)
108 780 50 0     4148 if $have6 or !defined $have6 && eval { ($have6||=0)||=do{require Socket6;1} }; # Only try to load Socket6 the first time Socket couldn't find something.
  75   0     665  
  75   50     13634  
  0   33     0  
      66        
      33        
109 780 50       2613 if (my $code = $sub->{$fullname}) {
110 76     76   575 no warnings qw(redefine prototype); # Don't spew when redefining the stub in the packages that imported it (as well as mine) with the REAL routine
  76         154  
  76         33323  
111 780 50       1430 eval { *{"$_\::$basename"}=$code foreach keys %{$exported->{$basename}}; *$fullname=$code } or warn "$fullname: On-The-Fly replacement failed: $@";
  780         1249  
  780         4738  
  295         3524  
  780         6556  
112 780         1704 my @res = (); # Run REAL routine preserving the same wantarray-ness context as caller
113 780 100       1210 eval { @res = $c[5] ? $code->(@_) : scalar $code->(@_); 1 } or do { (my $why=$@) =~ s/\s*at .* line \d.*//s; die "$why at $c[1] line $c[2]\n"; };
  780 50       35449  
  780         2495  
  0         0  
  0         0  
114 780 100       9479 return $c[5] ? @res : $res[0];
115             }
116 0         0 die "$basename is not a valid Socket macro and could not be imported at $c[1] line $c[2]\n";
117 76         702 };
118 76 100   76   707 foreach my $func (@EXPORT_OK) { eval { no strict 'refs'; *$func = sub { $stub_wrapper->($func,@_) }; } if !exists &$func; }
  76     780   154  
  76         7314  
  76         380  
  1900         5603  
  1672         475034  
  780         3394  
119             }
120              
121             # ($err, $hostname, $servicename) = safe_name_info($sockaddr, [$flags, [$xflags]])
122             # Compatibility routine to always act like Socket::getnameinfo even if it doesn't exist or if IO::Socket::IP is not available.
123             # XXX: Why are there two different versions of getnameinfo?
124             # The old Socket6 only allows for a single option $flags after the $sockaddr input and an error might be the first element. ($host,$sevice)=Socket6::getnameinfo($sockaddr, [$flags])
125             # The new Socket also allows for an optional $xflags input and always returns its $err as the first element, even on success.
126             sub safe_name_info {
127 211   33 211 0 533 my ($sockaddr, $flags, $xflags) = @_; $sockaddr ||= sockaddr_in 0, inet_aton "0.0.0.0"; $flags ||= 0; $xflags ||= 0;
  211   50     537  
  211   50     682  
  211         1172  
128 211         288 my @res;
129 211 50       330 eval { @res = getnameinfo $sockaddr, $flags, $xflags; 1 } or do { # Force 3-arg input to ensure old version will die: "Usage: Socket6::getnameinfo"
  211         992  
  211         528  
130 0         0 @res = getnameinfo $sockaddr, $flags; # Probably old Socket6 version, so hide NIx_* $xflags in $_[2]
131 0 0 0     0 @res<2 ? ($res[0]||="EAI_NONAME") : do {
132 0   0     0 @res = @res[-3,-2,-1]; $res[0] ||= ""; # Create first $err output element, if doesn't exist.
  0         0  
133 0 0       0 $res[NIx_NOHOST] = undef if $xflags & NIx_NOHOST; # Emulate $xflags
134 0 0       0 $res[NIx_NOSERV] = undef if $xflags & NIx_NOSERV; # so output matches
135             };
136             };
137 211         949 return @res;
138             }
139              
140             # ($err, @result) = safe_addr_info($host, $service, [$hints])
141             # Compatibility routine to always act like Socket::getaddrinfo even if IO::Socket::IP is not available.
142             # XXX: Why are there two different versions of getaddrinfo?
143             # The old Socket6 accepts a list of optional hints and returns either an $err or a multiple of 5 output. (@fiver_chunks)=Socket6::getaddrinfo($node,$port,[$family,$socktype,$proto,$flags])
144             # The new Socket accepts an optional HASHREF of hints and returns an $err followed by a list of HASHREFs.
145             sub safe_addr_info {
146 106   100 106 0 476 my ($host, $port, $hints) = @_; $host ||= ""; $port ||= 0;
  106   100     765  
  106         609  
147 106   50     286 $hints ||= {};
148 106         212 my @res;
149 106 50 33     1072 return @res = ('EAI_BADFLAGS: Usage: safe_addr_info($hostname, $servicename, \%hints)') if "HASH" ne ref $hints or @_ < 2 or @_ > 3;
      33        
150 106 50 0     5802 eval { @res = getaddrinfo( $host, $port, $hints ); die ($res[0] || "EAI_NONAME") if @res < 2; 1 } # Nice new Socket "HASH" method
  106         439  
  106         453  
151 106 50 0     315 or eval { # Convert Socket6 Old Array "C" method to "HASH" method
      33        
152 0         0 @res = (''); # Pretend like no error so far
153 0 0       0 my @results = getaddrinfo( $host, $port, map {$hints->{$_}||0} qw[family socktype protocol flags] );
  0         0  
154 0         0 while (@results > 4) {
155 0         0 my $r = {};
156 0         0 (@$r{qw[family socktype protocol addr canonname]}, @results) = @results;
157 0         0 push @res, $r;
158             }
159 0 0 0     0 $res[0] ||= "EAI_NONAME" if @res < 2;
160 0         0 1;
161             }
162             or $res[0] = ($@ || "getaddrinfo: failed $!");
163 106         441 return @res;
164             }
165              
166             # Capability test function (stolen from IO::Socket::IP in case only IO::Socket::INET6 is available)
167             sub CAN_DISABLE_V6ONLY {
168 92 100   92 0 713 return $can_disable_v6only if defined $can_disable_v6only;
169 9 50       478 socket my $testsock, AF_INET6, SOCK_STREAM, 0 or die "Cannot socket(PF_INET6) - $!";
170 9 50       54 setsockopt $testsock, IPPROTO_IPV6, IPV6_V6ONLY, 0 and return $can_disable_v6only = 1;
171 0 0 0 1   0 $!{EINVAL} || $!{EOPNOTSUPP} and return $can_disable_v6only = 0; # OpenBSD, WindowsXP, etc
  0         0  
  1         515  
  1         2731  
172 0         0 die "Cannot setsockopt(IPV6_V6ONLY) - $!";
173             }
174              
175             sub parse_info {
176 130 50   130 0 782 my $class = $_[0] eq __PACKAGE__ ? shift : __PACKAGE__;
177 130         442 my ($port, $host, $proto, $ipv, $server) = @_;
178              
179 130         301 my $info;
180 130 100       401 if (ref($port) eq 'HASH') {
181 12 50       44 croak "Missing port in hashref passed in port argument" if ! $port->{'port'};
182 12         26 $info = $port;
183             } else {
184 118         245 $info = {};
185 118 100       538 $info->{'unix_type'} = $1
186             if $port =~ s{ (?<=[\w*\]]) [,|\s:/]+ (sock_stream|sock_dgram) \b }{}x; # legacy /some/path|sock_dgram
187 118 100       1095 $ipv = $1 if $port =~ s{ (?<=[\w*\]]) [,|\s:/]+ IPv([*\d]+) }{}xi; # allow for 80|IPv*
188 118 100       465 $ipv .= $1 if $port =~ s{ (?<=[\w*\]]) [,|\s:/]+ IPv([*\d]+) }{}xi; # allow for 80|IPv4|IPv6 stacked
189 118 100 66     1539 $proto = $1 if $port =~ s{ (?<=[\w*\]]) [,|\s:/]+ (tcp|udp|ssl|ssleay|unix|unixdgram|\w+(?: ::\w+)+) $ }{}xi # allow for 80/tcp or 200/udp or 90/Net::Server::Proto::TCP
190             || $port =~ s{ / (\w+) $ }{}x; # legacy 80/MyTcp support
191 118 100       1116 $host = $1 if $port =~ s{ ^ (.*?) [,|\s:]+ (?= \w+ $) }{}x; # allow localhost:80
192 118         426 $info->{'port'} = $port;
193             }
194 130   50     384 $info->{'port'} ||= 0;
195              
196              
197 130 100 66     1501 $info->{'host'} ||= (defined($host) && length($host)) ? $host : '*';
      66        
198 130 100       497 $ipv = $1 if $info->{'host'} =~ s{ (?<=[\w*\]]) [,|\s:/]+ IPv([*\d]+) }{}xi; # allow for 80|IPv*
199 130 50       457 $ipv .= $1 if $info->{'host'} =~ s{ (?<=[\w*\]]) [,|\s:/]+ IPv([*\d]+) }{}xi; # allow for 80|IPv4|IPv6 stacked
200 130 100       1482 if ( $info->{'host'} =~ m{^ \[ ([\w/.\-:]+ | \*?) \] $ }x) { # allow for [::1] or [host.example.com]
    50          
201 4 50       20 $info->{'host'} = length($1) ? $1 : '*';
202             } elsif ($info->{'host'} =~ m{^ ([\w/.\-:]+ | \*?) $ }x) {
203 126         510 $info->{'host'} = $1; # untaint
204             } else {
205 0         0 $server->fatal("Could not determine host from \"$info->{'host'}\"");
206             }
207              
208              
209 130   100     1417 $info->{'proto'} ||= $proto || 'tcp';
      66        
210 130 100       406 $ipv = $1 if $info->{'proto'} =~ s{ (?<=[\w*\]]) [,|\s:/]+ IPv([*\d]+) }{}xi; # allow for 80|IPv*
211 130 50       355 $ipv .= $1 if $info->{'proto'} =~ s{ (?<=[\w*\]]) [,|\s:/]+ IPv([*\d]+) }{}xi; # allow for 80|IPv4|IPv6 stacked
212 130 50       3651 if ($info->{'proto'} =~ /^(\w+ (?:::\w+)*)$/x) {
213 130         388 $info->{'proto'} = $1;
214             } else {
215 0         0 $server->fatal("Could not determine proto from \"$proto\"");
216             }
217 130         545 $proto = lc $info->{'proto'};
218              
219 130 100       431 if ($info->{'proto'} =~ /^UNIX/i) {
220 8         89 return ({%$info, ipv => '*'});
221             }
222 122   100     1155 $ipv = $info->{'ipv'} || $ipv || $ENV{'IPV'} || '';
223 122 100       367 $ipv = join '', @$ipv if ref($ipv) eq 'ARRAY';
224 122 50 66     970 $server->fatal("Invalid ipv parameter - must contain 4, 6, or *") if $ipv && $ipv !~ /[46*]/;
225 122         221 my @_info;
226 122 100 100     1375 if (!$ipv || $ipv =~ /[*]/ and eval {CAN_DISABLE_V6ONLY}) {
  46 100 66     198  
      66        
227 46         83 my @rows = eval { $class->get_addr_info(@$info{qw(host port proto)}, $server) };
  46         397  
228 46 50 0     114 $server->fatal($@ || "Could not find valid addresses for [$info->{'host'}]:$info->{'port'} with ipv set to '*'") if ! @rows;
229 46         89 foreach my $row (@rows) {
230 46         158 my ($host, $port, $ipv, $warn) = @$row;
231 46 100       418 push @_info, {host => $host, port => $port, ipv => $ipv, proto => $info->{'proto'}, $warn ? (warn => $warn) : ()};
232             }
233 46 50 33     148 if (@rows > 1 && $rows[0]->[1] == 0) {
234 0         0 $server->log(2, "Determining auto-assigned port (0) for host $info->{'host'} (prebind)");
235 0         0 my $sock = $class->object($_info[-1], $server);
236 0         0 $sock->connect($server);
237 0         0 @$_{qw(port orig_port)} = ($sock->NS_port, 0) for @_info;
238             }
239 46         87 foreach my $_info (@_info) {
240             $server->log(2, "Resolved [$info->{'host'}]:$info->{'port'} to [$_info->{'host'}]:$_info->{'port'}, IPv$_info->{'ipv'}")
241 46 100 66     446 if $_info->{'host'} ne $info->{'host'} || $_info->{'port'} ne $info->{'port'};
242 46 100       234 $server->log(2, delete $_info->{'warn'}) if $_info->{'warn'};
243             }
244             } elsif ($ipv =~ /6/ || $info->{'host'} =~ /:/) {
245 19         200 push @_info, {%$info, ipv => '6'};
246 19 100 66     227 push @_info, {%$info, ipv => '4'} if $ipv =~ /4/ && $info->{'host'} !~ /:/;
247             } else {
248 57         448 push @_info, {%$info, ipv => '4'};
249             }
250              
251 122         985 return @_info;
252             }
253              
254             sub get_addr_info {
255 107 50   107 0 5533 my $class = $_[0] eq __PACKAGE__ ? shift : __PACKAGE__;
256 107         395 my ($host, $port, $proto, $server) = @_;
257 107 50       351 $host = '*' if ! defined $host;
258 107 100       422 $port = 0 if ! defined $port;
259 107 100       359 $proto = 'tcp' if ! defined $proto;
260 107 100       341 $server = {} if ! defined $server;
261 107 50       417 return ([$host, $port, '*']) if $proto =~ /UNIX/i;
262 107 50 0     506 $port = (getservbyname($port, $proto))[2] or croak "Could not determine port number from host [$host]:$_[1]" if $port =~ /\D/;
263              
264 107         237 my @info;
265 107 100       413 if ($host =~ /^\d+(?:\.\d+){3}$/) {
    50          
    0          
266 1 50       3 my $addr = inet_aton($host) or croak "Unresolveable host [$host]:$port: invalid ip";
267 1         4 push @info, [inet_ntoa($addr), $port, 4];
268 106         453 } elsif (eval { AI_PASSIVE }) { # PreTest to ensure AddressInfo AI_* operations can even try on this platform.
269 106 50       19479 my $proto_id = getprotobyname(lc($proto) eq 'udp' ? 'udp' : 'tcp');
270 106 50       871 my $socktype = lc($proto) eq 'udp' ? SOCK_DGRAM : SOCK_STREAM;
271 106 100       800 my @res = safe_addr_info($host eq '*' ? '' : $host, $port, { family=>AF_UNSPEC, socktype=>$socktype, protocol=>$proto_id, flags=>AI_PASSIVE });
272 106 50 33     397 my $err = shift @res; croak "Unresolveable [$host]:$port: $err" if $err or (@res < 1 and $err = "getaddrname: $host: FAILURE!");
  106   33     690  
273 106         390 while (my $r = shift @res) {
274 211         795 my ($err, $ip) = safe_name_info($r->{addr}, NI_NUMERICHOST | NI_NUMERICSERV);
275 211 50 33     904 croak "safe_name_info failed on [$host]:$port [$err]" if $err || !$ip;
276 211 50       829 my $ipv = ($r->{family} == AF_INET) ? 4 : ($r->{family} == AF_INET6) ? 6 : '*';
    100          
277 211         1153 push @info, [$ip, $port, $ipv];
278             }
279 106 50       445 my %ipv6mapped = map {$_->[0] eq '::' ? ('0.0.0.0' => $_) : $_->[0] =~ /^::ffff:(\d+(?:\.\d+){3})$/i ? ($1 => $_) : ()} @info;
  211 100       999  
280 106 100 66     701 if (keys %ipv6mapped and grep {$ipv6mapped{$_->[0]}} @info) {
  88         268  
281 44         102 for my $i4 (@info) {
282 88 100       291 my $i6 = $ipv6mapped{$i4->[0]} or next;
283 44 100 33     56 if (!eval{ipv6_package($server)->new(LocalAddr=>$i6->[0],Type=>$socktype)}) {
  44 50       137  
284 1         5 $i4->[3] = "Host [$host] resolved to IPv6 address [$i6->[0]] but ipv6_package->new fails: $@";
285 1         4 $i6->[0] = '';
286 43         3745 } elsif ($i6->[2] eq '6' and eval {CAN_DISABLE_V6ONLY}) { # If IPv* can bind to both, upgrade '6' to '*', and disable the corresponding '4' entry
287 43         157 $i6->[3] = "Not including resolved host [$i4->[0]] IPv4 because it will be handled by [$i6->[0]] IPv6";
288 43         81 $i6->[2] = '*';
289 43         1172 $i4->[0] = '';
290             }
291             }
292 44         91 @info = grep {length $_->[0]} @info;
  88         333  
293             }
294             } elsif ($host =~ /:/) {
295 0         0 croak "Unresolveable host [$host]:$port - could not load IPv6: $@";
296             } else {
297 0         0 my @addr;
298 0 0       0 if ($host eq '*') {
299 0         0 push @addr, INADDR_ANY;
300             } else {
301 0         0 (undef, undef, undef, undef, @addr) = gethostbyname($host);
302 0 0       0 croak "Unresolveable host [$host]:$port via IPv4 gethostbyname" if !@addr;
303             }
304 0         0 push @info, [inet_ntoa($_), $port, 4] for @addr
305             }
306              
307 107         532 return @info;
308             }
309              
310             sub object {
311 136 50   136 1 789 my $class = $_[0] eq __PACKAGE__ ? shift : __PACKAGE__;
312 136         300 my ($info, $server) = @_;
313 136         310 my $proto_class = $info->{'proto'};
314 136 100       607 if ($proto_class !~ /::/) {
315 135 50       847 $server->fatal("Invalid proto class \"$proto_class\"") if $proto_class !~ /^\w+$/;
316 135         437 $proto_class = "Net::Server::Proto::" .uc($proto_class);
317             }
318 136         1060 (my $file = "${proto_class}.pm") =~ s|::|/|g;
319 136 50       312 $server->fatal("Unable to load module for proto \"$proto_class\": $@") if ! eval { require $file;1 };
  136         53702  
  136         712  
320 136 100       518 ipv6_package($server) if $server->{'server'}->{'ipv6_package'};
321 136         1163 return $proto_class->object($info, $server);
322             }
323              
324             sub ipv6_package {
325 81 100   81 0 429639 return $ipv6_package if $ipv6_package;
326 28 100       503 return undef if $ENV{'NO_IPV6'};
327 25 100 100     994 my $class = @_ && $_[0] eq __PACKAGE__ ? shift : __PACKAGE__;
328 25   100     840 my $server = shift || {};
329 25 50 33     278 eval {require Net::Server::IP;1} or !warn "ipv6_package: Failure! [$!] [$@]" or die "ipv6_package: Failure! [$!] [$@]";
  25         1447  
  25         1185  
330 25 100 100     1254 if (!$Net::Server::IP::ipv6_package and my $pkg = $server->{'server'} && $server->{'server'}->{'ipv6_package'}) {
      100        
331 4         23 $Net::Server::IP::ipv6_package = $pkg;
332             }
333 25         1178 return $ipv6_package = "Net::Server::IP";
334             }
335              
336             our $IPV6_V6ONLY;
337             sub IPV6_V6ONLY () {
338 1 50   1 0 6 return $IPV6_V6ONLY if $IPV6_V6ONLY;
339 1         2 $IPV6_V6ONLY = eval { Socket::IPV6_V6ONLY() }; # First try the actual platform value
  1         4  
340 1         3 my $why = $@; # XXX: Do we need to hard-code magic numbers based on OS for old Perl < 5.14 / Socket < 1.94?
341 1 0 33     4 $IPV6_V6ONLY ||= $^O eq 'linux' ? 26 : # XXX: Why is Linux different?
    0          
342             $^O =~ /^(?:darwin|freebsd|openbsd|netbsd|dragonfly|MSWin32|solaris|svr4)$/ ? 27 : undef; # XXX: "27" everywhere else?
343 1 50       5 if (!$IPV6_V6ONLY) { # XXX: Do we need to scrape it from kernel header files? Last ditch effort super ugly string-eval hack!
344 0 0 0     0 my $d = "/tmp/IP6Cache"; !eval{$IPV6_V6ONLY=do"$d.pl"} and $IPV6_V6ONLY=do{mkdir $d;`h2ph -d $d -a netinet/in.h 2>/dev/null`;eval `echo "package _h2ph_shush_ipv6only;";grep -rl "sub IPV6_V6ONLY" $d|xargs cat|grep "sub IPV6_V6ONLY";echo "IPV6_V6ONLY()"`} and `rm -rvf $d 1>&2;echo $IPV6_V6ONLY|tee $d.pl`;
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
345             }
346 1 50       3 if ($IPV6_V6ONLY) {
347 1     0   13 my $bricker=sub(){$IPV6_V6ONLY}; (my $me=(caller 0)[3])=~s/.*:://;
  0         0  
  1         19  
348 76     76   7769 no strict 'refs';no warnings qw(redefine);*{"$_\::$me"}=$bricker foreach keys %{$exported->{$me}},__PACKAGE__;
  76     76   170  
  76         3843  
  76         577  
  76         235  
  76         18280  
  1         5  
  1         5  
  2         19  
349 1         49 return $IPV6_V6ONLY;
350             }
351 0         0 croak "$why\n$@\n[Socket $Socket::VERSION] Could not determine IPV6_V6ONLY on Unknown Platform [$^O]";
352             }
353              
354             1;
355              
356             __END__