2014-09-16 01:58:21 +02:00
|
|
|
package Qpsmtpd::Base;
|
2002-09-24 20:53:45 +02:00
|
|
|
use strict;
|
|
|
|
|
2014-11-06 03:02:58 +01:00
|
|
|
use Net::DNS;
|
2014-09-11 22:34:32 +02:00
|
|
|
use Net::IP;
|
|
|
|
|
2014-09-16 08:41:31 +02:00
|
|
|
sub new {
|
|
|
|
return bless {}, shift;
|
|
|
|
};
|
|
|
|
|
2002-09-24 20:53:45 +02:00
|
|
|
sub tildeexp {
|
2014-09-10 22:43:46 +02:00
|
|
|
my ($self, $path) = @_;
|
2014-09-16 14:11:54 +02:00
|
|
|
$path =~ s{^~([^/]*)} {
|
|
|
|
$1 ? (getpwnam($1))[7]
|
|
|
|
: ( $ENV{HOME} || $ENV{LOGDIR} || (getpwuid($>))[7])
|
|
|
|
}ex;
|
2002-09-24 20:53:45 +02:00
|
|
|
return $path;
|
|
|
|
}
|
|
|
|
|
2014-09-10 22:43:46 +02:00
|
|
|
sub is_localhost {
|
|
|
|
my ($self, $ip) = @_;
|
|
|
|
return if ! $ip;
|
|
|
|
return 1 if $ip =~ /^127\./; # IPv4
|
|
|
|
return 1 if $ip =~ /:127\./; # IPv4 mapped IPv6
|
|
|
|
return 1 if $ip eq '::1'; # IPv6
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-09-11 22:34:32 +02:00
|
|
|
sub is_valid_ip {
|
|
|
|
my ($self, $ip) = @_;
|
|
|
|
|
|
|
|
if (Net::IP::ip_is_ipv4($ip)) {
|
|
|
|
return if $ip eq '0.0.0.0';
|
|
|
|
return if $ip eq '255.255.255.255';
|
|
|
|
return if $ip =~ /255/;
|
|
|
|
return 1;
|
|
|
|
};
|
|
|
|
return 1 if Net::IP::ip_is_ipv6($ip);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-11-05 22:50:19 +01:00
|
|
|
sub is_ipv6 {
|
|
|
|
my ($self, $ip) = @_;
|
|
|
|
return if !$ip;
|
2014-11-05 23:31:44 +01:00
|
|
|
return Net::IP::ip_is_ipv6($ip);
|
2014-11-05 22:50:19 +01:00
|
|
|
};
|
|
|
|
|
2014-11-06 03:02:58 +01:00
|
|
|
sub get_resolver {
|
|
|
|
my ($self, %args) = @_;
|
|
|
|
return $self->{_resolver} if $self->{_resolver};
|
|
|
|
my $timeout = 5;
|
|
|
|
if (defined $args{timeout}) {
|
|
|
|
$timeout = delete $args{timeout};
|
|
|
|
}
|
|
|
|
$self->{_resolver} = Net::DNS::Resolver->new(dnsrch => 0);
|
|
|
|
$self->{_resolver}->tcp_timeout($timeout);
|
|
|
|
$self->{_resolver}->udp_timeout($timeout);
|
|
|
|
return $self->{_resolver};
|
|
|
|
}
|
|
|
|
|
|
|
|
sub get_async_resolver {
|
|
|
|
my ( $self, %args ) = @_;
|
|
|
|
return $self->{_async_resolver} if $self->{_async_resolver};
|
|
|
|
|
|
|
|
my $res = Net::DNS::Resolver->new(dnsrch => 0);
|
|
|
|
$res->tcp_timeout(0); # Net::DNS::Async handles its own timeouts
|
|
|
|
$res->tcp_timeout(0);
|
|
|
|
|
|
|
|
my $async_res;
|
|
|
|
eval 'use Net::DNS::Async';
|
|
|
|
if ($@) {
|
|
|
|
warn "Net::DNS::Async failed to load";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$self->{_async_resolver} = Net::DNS::Async->new( %args );
|
|
|
|
$self->{_async_resolver}{Resolver} = $res;
|
|
|
|
return $self->{_async_resolver};
|
|
|
|
}
|
|
|
|
|
|
|
|
sub resolve_a {
|
|
|
|
my ($self, $name) = @_;
|
|
|
|
my $q = $self->get_resolver->query($name, 'A') or return;
|
|
|
|
return map { $_->address } grep { $_->type eq 'A' } $q->answer;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub resolve_aaaa {
|
|
|
|
my ($self, $name) = @_;
|
|
|
|
my $q = $self->get_resolver->query($name, 'AAAA') or return;
|
|
|
|
return map { $_->address } grep { $_->type eq 'AAAA' } $q->answer;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub resolve_mx {
|
|
|
|
my ($self, $name) = @_;
|
|
|
|
my $q = $self->get_resolver->query($name, 'MX') or return;
|
|
|
|
return map { $_->exchange } grep { $_->type eq 'MX' } $q->answer;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub resolve_ns {
|
|
|
|
my ($self, $name) = @_;
|
|
|
|
my $q = $self->get_resolver->query($name, 'NS') or return;
|
|
|
|
return map { $_->nsdname } grep { $_->type eq 'NS' } $q->answer;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub resolve_ptr {
|
|
|
|
my ($self, $name) = @_;
|
|
|
|
my $q = $self->get_resolver->query($name, 'PTR') or return;
|
|
|
|
return map { $_->ptrdname } grep { $_->type eq 'PTR' } $q->answer;
|
|
|
|
}
|
|
|
|
|
2002-09-24 20:53:45 +02:00
|
|
|
1;
|