Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect if system supports ipv6?

Tags:

perl

ipv6

I finally managed to fix ipv6 support in my software. Unfortunately, now it crashes on every ipv4 only machine. Here is the faulty subroutine:

sub init
{
    my ($self, %opts) = @_;

    # server options defaults
    my %defaults = (StartBackground => 0, ServerPort => 3000);

    # set options or use defaults
    map { $self->{$_} = (exists $opts{$_} ? $opts{$_} : $defaults{$_}) }
        keys %defaults;

    $self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'}, Socket::AF_INET6);

    return $self;
}

The problem here is in the second last line:

$self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'}, Socket::AF_INET6);

As on ipv4 only machine it dies complaining about a not supported address family (which is the second parameter passed to the new function).

Basically, what I need to do is:

if (it_supports_ipv6()) {
    $self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'}, Socket::AF_INET6);
}
else {
    $self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'});
}

But how to implement a function like it_supports_ipv6()?

I tried with eval with the following syntax, but it doesn't work:

my $ipv6_success = eval { $self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'}, Socket::AF_INET6); };
if (!defined($ipv6_success)) {
    $self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'});
}

The logic is that I've read in eval doc that it returns undef if the expression causes the program to die.

I'm working on a Linux machine.

like image 573
Zagorax Avatar asked Aug 31 '25 23:08

Zagorax


1 Answers

Don't trust the has_ipv6() function in Paranoid::Network::Socket. It returns false positive as it just checks if Perl supports it, but this isn't enough at all (the system, as example, could lack ipv6 kernel module loaded).

I ended up with the following function and it seems to work fine.

use IO::Socket::IP;

sub supports_ipv6 {
    my $has_ipv6;

    eval {
        $has_ipv6 = IO::Socket::IP->new (
            Domain => PF_INET6,
            LocalHost => '::1',
            Listen => 1 ) or die;
    };

    if ($@) {
        return 0;
    }
    else {
        return 1;
    }
}
like image 56
Zagorax Avatar answered Sep 04 '25 02:09

Zagorax