The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl

use strict;
use warnings;
use lib './lib';

use English qw(-no_match_vars);
use Getopt::Long;
use Pod::Usage;

use FusionInventory::Agent::Task::NetDiscovery;
use FusionInventory::Agent::Logger;

my $options = {
    threads   => 1
};

my %setup = (
    confdir => './etc',
    datadir => './share',
    libdir  => './lib',
    vardir  => './var',
);

GetOptions(
    $options,
    'first=s',
    'last=s',
    'community=s@',
    'credential=s@',
    'entity=s',
    'threads=i',
    'timeout=i',
    'verbose',
    'debug+',
    'help',
    'version'
) or pod2usage(-verbose => 0);

if ($options->{version}) {
  print "NetDiscovery task $FusionInventory::Agent::Task::NetDiscovery::VERSION\n";
  exit 0;
}
pod2usage(-verbose => 0, -exitval => 0) if $options->{help};

pod2usage(
    -message => "no first address, aborting\n", -verbose => 0
) unless $options->{first};
pod2usage(
    -message => "no last address, aborting\n", -verbose => 0
) unless $options->{last};

my $discovery = FusionInventory::Agent::Task::NetDiscovery->new(
    %setup,
    target => FusionInventory::Agent::Task::NetInventory::Target->new(),
    logger =>  FusionInventory::Agent::Logger->new(
        debug => $options->{debug}
    )
);

my $credentials_id = 1;
my @credentials;
if ($options->{community}) {
    foreach my $community (@{$options->{community}}) {
        push @credentials,
            { ID => $credentials_id++, VERSION => 1, COMMUNITY => $community };
    }
} elsif ($options->{credential}) {
    foreach my $specification (@{$options->{credential}}) {
        my $credential = { ID => $credentials_id++ };
        foreach my $parameter (split(',', $specification)) {
            my ($key, $value) = split(':', $parameter);
            $credential->{uc($key)} = $value;
        }
        push @credentials, $credential;
    }
} else {
    push @credentials, {
        ID => $credentials_id++, VERSION => 1, COMMUNITY => 'public'
    };
}

$discovery->{options} = {
    NAME => 'NETDISCOVERY',
    PARAM => [
        {
            PID               => 1,
            THREADS_DISCOVERY => $options->{threads},
            TIMEOUT           => $options->{timeout},
        }
    ],
    RANGEIP => [
        {
            ID      => 1,
            IPSTART => $options->{first},
            IPEND   => $options->{last},
        }
    ],
    AUTHENTICATION => \@credentials
};
if (defined($options->{entity})) {
    $discovery->{options}->{RANGEIP}->[0]->{ENTITY} = $options->{entity};
}
$discovery->{client} =
    FusionInventory::Agent::Task::NetInventory::Client->new(
        verbose => $options->{verbose}
    );
$discovery->{deviceid} = 'foo';

$discovery->run();

package FusionInventory::Agent::Task::NetInventory::Client;

sub new {
    my ($class, %params) = @_;

    return bless {
        verbose => $params{verbose}
    }, $class;
}

sub send {
    my ($self, %params) = @_;

    # don't display control message by default
    return unless $self->{verbose}
        or $params{message}->{h}->{CONTENT}->{DEVICE};

    print $params{message}->getContent();
}

package FusionInventory::Agent::Task::NetInventory::Target;

sub new {
    my ($class, %params) = @_;

    return bless {}, $class;
}

sub getUrl {
    my ($self, %params) = @_;

    ## no critic (ExplicitReturnUndef)
    return undef;
}

__END__

=head1 NAME

fusioninventory-netdiscovery - Standalone network discovery

=head1 SYNOPSIS

fusioninventory-netdiscovery [options] --first <start> --last <stop>

  Options:
    --first address IP range first address
    --last address  IP range last address
    --credential    SNMP credential (default: version:1,community:public)
    --entity        GLPI entity
    --threads nb    number of discovery threads (default: 1)
    --timeout val   SNMP timeout (default: 1s)
    --verbose       verbose output (control messages)
    --debug         debug output (execution traces)
    -h --help       print this message and exit
    --version       print the task version and exit

=head1 DESCRIPTION

F<fusioninventory-netdiscovery> allows to run a network discovery task without a
GLPI server.