package Qpsmtpd::Base; use strict; use Net::DNS; use Net::IP; sub new { return bless {}, shift; } sub tildeexp { my ($self, $path) = @_; $path =~ s{^~([^/]*)} { $1 ? (getpwnam($1))[7] : ( $ENV{HOME} || $ENV{LOGDIR} || (getpwuid($>))[7]) }ex; return $path; } 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; } 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; } sub is_ipv6 { my ($self, $ip) = @_; return if !$ip; return Net::IP::ip_is_ipv6($ip); } 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 $async_res; eval 'use Net::DNS::Async'; if ($@) { warn "could not load Net::DNS::Async, is it installed?"; return; } my $res = Net::DNS::Resolver->new(dnsrch => 0); $res->tcp_timeout(0); # Net::DNS::Async handles its own timeouts $res->tcp_timeout(0); $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; } 1;