Merge pull request #216 from msimerson/tcpserver2

Tcpserver2
This commit is contained in:
Matt Simerson 2015-01-29 00:23:07 -08:00
commit fddf571988

View File

@ -5,9 +5,12 @@ use POSIX ();
use Socket; use Socket;
use lib 'lib'; use lib 'lib';
use Qpsmtpd::Base;
use Qpsmtpd::Constants; use Qpsmtpd::Constants;
use parent 'Qpsmtpd::SMTP'; use parent 'Qpsmtpd::SMTP';
my $base = Qpsmtpd::Base->new();
my $has_ipv6 = 0; my $has_ipv6 = 0;
if ( if (
eval { require Socket6; } && eval { require Socket6; } &&
@ -24,62 +27,71 @@ sub has_ipv6 {
my $first_0; my $first_0;
sub conn_info_tcpserver {
# started from tcpserver (or some other superserver which
# exports the TCPREMOTE* variables.
my $r_host = $ENV{TCPREMOTEHOST} || '[' . $ENV{TCPREMOTEIP} . ']';
return (
local_ip => $ENV{TCPLOCALIP},
local_host => $ENV{TCPLOCALHOST},
local_port => $ENV{TCPLOCALPORT},
remote_ip => $ENV{TCPREMOTEIP},
remote_host => $r_host,
remote_info => $ENV{TCPREMOTEINFO} ? "$ENV{TCPREMOTEINFO}\@$r_host" : $r_host,
remote_port => $ENV{TCPREMOTEPORT},
)
}
sub conn_info_inetd {
my $self = shift;
# Started from inetd or similar.
# get info on the remote host from the socket.
# ignore ident/tap/...
my $hersockaddr = getpeername(STDIN) or die "getpeername failed:" .
" $0 must be called from tcpserver, (x)inetd or" .
" a similar program which passes a socket to stdin";
my ($r_port, $iaddr) = sockaddr_in($hersockaddr);
my $r_ip = inet_ntoa($iaddr);
my ($r_host) = $base->resolve_ptr($r_ip) || "[$r_ip]";
return (
local_ip => '',
local_host => '',
local_port => '',
remote_ip => $r_ip,
remote_host => $r_host,
remote_info => $r_host,
remote_port => $r_port,
)
}
sub start_connection { sub start_connection {
my $self = shift; my $self = shift;
my ( my %info;
$remote_host, $remote_info, $remote_ip, $remote_port,
$local_ip, $local_port, $local_host
);
if ($ENV{TCPREMOTEIP}) { if ($ENV{TCPREMOTEIP}) {
%info = $self->conn_info_tcpserver();
# started from tcpserver (or some other superserver which
# exports the TCPREMOTE* variables.
$remote_ip = $ENV{TCPREMOTEIP};
$remote_host = $ENV{TCPREMOTEHOST} || "[$remote_ip]";
$remote_info =
$ENV{TCPREMOTEINFO}
? "$ENV{TCPREMOTEINFO}\@$remote_host"
: $remote_host;
$remote_port = $ENV{TCPREMOTEPORT};
$local_ip = $ENV{TCPLOCALIP};
$local_port = $ENV{TCPLOCALPORT};
$local_host = $ENV{TCPLOCALHOST};
} }
else { else {
# Started from inetd or similar. %info = $self->conn_info_inetd();
# get info on the remote host from the socket.
# ignore ident/tap/...
my $hersockaddr = getpeername(STDIN)
or die
"getpeername failed: $0 must be called from tcpserver, (x)inetd or a similar program which passes a socket to stdin";
my ($port, $iaddr) = sockaddr_in($hersockaddr);
$remote_ip = inet_ntoa($iaddr);
$remote_host = gethostbyaddr($iaddr, AF_INET) || "[$remote_ip]";
$remote_info = $remote_host;
} }
$self->log(LOGNOTICE, "Connection from $remote_info [$remote_ip]"); $self->log(LOGNOTICE, "Connection from $info{remote_info} [$info{remote_ip}]");
# if the local dns resolver doesn't filter it out we might get # if the local dns resolver doesn't filter it out we might get
# ansi escape characters that could make a ps axw do "funny" # ansi escape characters that could make a ps axw do "funny"
# things. So to be safe, cut them out. # things. So to be safe, cut them out.
$remote_host =~ tr/a-zA-Z\.\-0-9\[\]//cd; $info{remote_host} =~ tr/a-zA-Z\.\-0-9\[\]//cd;
$first_0 = $0 unless $first_0; $first_0 = $0 unless $first_0;
my $now = POSIX::strftime("%H:%M:%S %Y-%m-%d", localtime); my $now = POSIX::strftime("%H:%M:%S %Y-%m-%d", localtime);
$0 = "$first_0 [$remote_ip : $remote_host : $now]"; $0 = "$first_0 [$info{remote_ip} : $info{remote_host} : $now]";
$self->SUPER::connection->start( $self->SUPER::connection->start(%info, @_);
remote_info => $remote_info,
remote_ip => $remote_ip,
remote_host => $remote_host,
remote_port => $remote_port,
local_ip => $local_ip,
local_port => $local_port,
local_host => $local_host,
@_
);
} }
sub run { sub run {
@ -183,7 +195,9 @@ sub tcpenv {
return $TCPLOCALIP, $TCPREMOTEIP, return $TCPLOCALIP, $TCPREMOTEIP,
$TCPREMOTEIP ? "[$ENV{TCPREMOTEIP}]" : "[noip!]"; $TCPREMOTEIP ? "[$ENV{TCPREMOTEIP}]" : "[noip!]";
} }
my ($TCPREMOTEHOST) = $self->resolve_ptr($TCPREMOTEIP) || 'Unknown'; my ($TCPREMOTEHOST) = $base->resolve_ptr($TCPREMOTEIP);
$TCPREMOTEHOST ||= 'Unknown';
return $TCPLOCALIP, $TCPREMOTEIP, $TCPREMOTEHOST; return $TCPLOCALIP, $TCPREMOTEIP, $TCPREMOTEHOST;
} }