261 lines
5.9 KiB
Perl
261 lines
5.9 KiB
Perl
package App::Netdisco::DB::ResultSet::NodeIp;
|
|
use base 'App::Netdisco::DB::ResultSet';
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
__PACKAGE__->load_components(qw/
|
|
+App::Netdisco::DB::ExplicitLocking
|
|
/);
|
|
|
|
my $order_by_time_last_and_join_oui = {
|
|
order_by => {'-desc' => 'time_last'},
|
|
'+columns' => [
|
|
'oui.company',
|
|
'oui.abbrev',
|
|
{ time_first_stamp => \"to_char(time_first, 'YYYY-MM-DD HH24:MI')" },
|
|
{ time_last_stamp => \"to_char(time_last, 'YYYY-MM-DD HH24:MI')" },
|
|
],
|
|
join => 'oui'
|
|
};
|
|
|
|
=head1 with_times
|
|
|
|
This is a modifier for any C<search()> (including the helpers below) which
|
|
will add the following additional synthesized columns to the result set:
|
|
|
|
=over 4
|
|
|
|
=item time_first_stamp
|
|
|
|
=item time_last_stamp
|
|
|
|
=back
|
|
|
|
=cut
|
|
|
|
sub with_times {
|
|
my ($rs, $cond, $attrs) = @_;
|
|
|
|
return $rs
|
|
->search_rs({}, $order_by_time_last_and_join_oui)
|
|
->search($cond, $attrs);
|
|
}
|
|
|
|
=head1 search_by_ip( \%cond, \%attrs? )
|
|
|
|
my $set = $rs->search_by_ip({ip => '192.0.2.1', active => 1});
|
|
|
|
Like C<search()>, this returns a ResultSet of matching rows from the
|
|
NodeIp table.
|
|
|
|
=over 4
|
|
|
|
=item *
|
|
|
|
The C<cond> parameter must be a hashref containing a key C<ip> with the value
|
|
to search for. Value can either be a simple string of IPv4 or IPv6, or a
|
|
L<NetAddr::IP::Lite> object in which case all results within the CIDR/Prefix
|
|
will be retrieved.
|
|
|
|
=item *
|
|
|
|
Results are ordered by time last seen.
|
|
|
|
=item *
|
|
|
|
Additional columns C<time_first_stamp> and C<time_last_stamp> provide
|
|
preformatted timestamps of the C<time_first> and C<time_last> fields.
|
|
|
|
=item *
|
|
|
|
A JOIN is performed on the OUI table and the OUI C<company> column prefetched.
|
|
|
|
=back
|
|
|
|
To limit results only to active IPs, set C<< {active => 1} >> in C<cond>.
|
|
|
|
=cut
|
|
|
|
sub search_by_ip {
|
|
my ($rs, $cond, $attrs) = @_;
|
|
|
|
die "ip address required for search_by_ip\n"
|
|
if ref {} ne ref $cond or !exists $cond->{ip};
|
|
|
|
# handle either plain text IP or NetAddr::IP (/32 or CIDR)
|
|
my ($op, $ip) = ('=', delete $cond->{ip});
|
|
|
|
if ('NetAddr::IP::Lite' eq ref $ip and $ip->num > 1) {
|
|
$op = '<<=';
|
|
$ip = $ip->cidr;
|
|
}
|
|
$cond->{ip} = { $op => $ip };
|
|
|
|
return $rs
|
|
->search_rs({}, $order_by_time_last_and_join_oui)
|
|
->search($cond, $attrs);
|
|
}
|
|
|
|
=head1 search_by_dns( \%cond, \%attrs? )
|
|
|
|
my $set = $rs->search_by_dns({
|
|
dns => 'foo.example.com',
|
|
suffix => qr/(?:\.example\..com|\.local)$/,
|
|
active => 1
|
|
});
|
|
|
|
Like C<search()>, this returns a ResultSet of matching rows from the
|
|
NodeIp table.
|
|
|
|
=over 4
|
|
|
|
=item *
|
|
|
|
The NodeIp table must have a C<dns> column for this search to work. Typically
|
|
this column is the IP's DNS PTR record, cached at the time of Netdisco Arpnip.
|
|
|
|
=item *
|
|
|
|
The C<cond> parameter must be a hashref containing a key C<dns> with the value
|
|
to search for. The value may optionally include SQL wildcard characters.
|
|
|
|
=item *
|
|
|
|
If C<dns> is a plain string, then the C<cond> parameter may optionally have a
|
|
C<suffix> parameter which is a regular expression of domain names - one of
|
|
which must match the results.
|
|
|
|
=item *
|
|
|
|
Results are ordered by time last seen.
|
|
|
|
=item *
|
|
|
|
Additional columns C<time_first_stamp> and C<time_last_stamp> provide
|
|
preformatted timestamps of the C<time_first> and C<time_last> fields.
|
|
|
|
=item *
|
|
|
|
A JOIN is performed on the OUI table and the OUI C<company> column prefetched.
|
|
|
|
=back
|
|
|
|
To limit results only to active IPs, set C<< {active => 1} >> in C<cond>.
|
|
|
|
=cut
|
|
|
|
sub search_by_dns {
|
|
my ($rs, $cond, $attrs) = @_;
|
|
|
|
die "dns field required for search_by_dns\n"
|
|
if ref {} ne ref $cond or !exists $cond->{dns};
|
|
|
|
my $dns_field = delete $cond->{dns};
|
|
|
|
(my $suffix = ($cond->{suffix} || ''))
|
|
=~ s|\Q(?^\E[-xismu]*|(?|g;
|
|
|
|
if (q{} eq ref $dns_field and exists $cond->{suffix}) {
|
|
(my $stripped_dns_field = $dns_field) =~ s/\.\%$//;
|
|
(my $fqdn_field = $stripped_dns_field) .= '%';
|
|
$stripped_dns_field =~ s/$cond->{suffix}$// if $cond->{suffix};
|
|
$stripped_dns_field .= '.%';
|
|
|
|
$cond->{dns} = [ -or =>
|
|
[ -and =>
|
|
{ '-ilike' => $stripped_dns_field },
|
|
{ '~*' => "***:$suffix" },
|
|
],
|
|
[ -and =>
|
|
{ '-ilike' => $dns_field },
|
|
{ '~*' => "***:$suffix" },
|
|
],
|
|
{ '-ilike' => $fqdn_field },
|
|
];
|
|
}
|
|
elsif (q{} ne ref $dns_field) {
|
|
$cond->{dns} = $dns_field;
|
|
}
|
|
else {
|
|
$cond->{dns} = { '-ilike' => $dns_field };
|
|
}
|
|
|
|
delete $cond->{suffix};
|
|
return $rs
|
|
->search_rs({}, $order_by_time_last_and_join_oui)
|
|
->search($cond, $attrs);
|
|
}
|
|
|
|
=head1 search_by_mac( \%cond, \%attrs? )
|
|
|
|
my $set = $rs->search_by_mac({mac => '00:11:22:33:44:55', active => 1});
|
|
|
|
Like C<search()>, this returns a ResultSet of matching rows from the
|
|
NodeIp table.
|
|
|
|
=over 4
|
|
|
|
=item *
|
|
|
|
The C<cond> parameter must be a hashref containing a key C<mac> with the value
|
|
to search for.
|
|
|
|
=item *
|
|
|
|
Results are ordered by time last seen.
|
|
|
|
=item *
|
|
|
|
Additional columns C<time_first_stamp> and C<time_last_stamp> provide
|
|
preformatted timestamps of the C<time_first> and C<time_last> fields.
|
|
|
|
=item *
|
|
|
|
A JOIN is performed on the OUI table and the OUI C<company> column prefetched.
|
|
|
|
=back
|
|
|
|
To limit results only to active IPs, set C<< {active => 1} >> in C<cond>.
|
|
|
|
=cut
|
|
|
|
sub search_by_mac {
|
|
my ($rs, $cond, $attrs) = @_;
|
|
|
|
die "mac address required for search_by_mac\n"
|
|
if ref {} ne ref $cond or !exists $cond->{mac};
|
|
|
|
return $rs
|
|
->search_rs({}, $order_by_time_last_and_join_oui)
|
|
->search($cond, $attrs);
|
|
}
|
|
|
|
=head2 ip_version( $version )
|
|
|
|
my $rset = $rs->ip_version(4);
|
|
|
|
This predefined C<search()> returns a ResultSet of matching rows from the
|
|
NodeIp table of nodes with addresses of the supplied IP version.
|
|
|
|
=over 4
|
|
|
|
=item *
|
|
|
|
The C<version> parameter must be an integer either 4 or 6.
|
|
|
|
=back
|
|
|
|
=cut
|
|
|
|
sub ip_version {
|
|
my ( $rs, $version ) = @_;
|
|
|
|
die "ip_version input must be either 4 or 6\n"
|
|
unless $version && ( $version == 4 || $version == 6 );
|
|
|
|
return $rs->search_rs( \[ 'family(me.ip) = ?', $version ] );
|
|
}
|
|
|
|
1;
|