From 98d148a0bf7321a6db1a860a46c6d967aed26663 Mon Sep 17 00:00:00 2001 From: Matt Simerson Date: Wed, 28 Jan 2015 22:54:04 -0800 Subject: [PATCH 1/2] refactor start_connection --- lib/Qpsmtpd/TcpServer.pm | 92 ++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 41 deletions(-) diff --git a/lib/Qpsmtpd/TcpServer.pm b/lib/Qpsmtpd/TcpServer.pm index a436f6d..4cff8ec 100644 --- a/lib/Qpsmtpd/TcpServer.pm +++ b/lib/Qpsmtpd/TcpServer.pm @@ -6,6 +6,7 @@ use Socket; use lib 'lib'; use Qpsmtpd::Constants; +use parent 'Qpsmtpd::Base'; use parent 'Qpsmtpd::SMTP'; my $has_ipv6 = 0; @@ -24,62 +25,71 @@ sub has_ipv6 { 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) = $self->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 { my $self = shift; - my ( - $remote_host, $remote_info, $remote_ip, $remote_port, - $local_ip, $local_port, $local_host - ); - + my %info; if ($ENV{TCPREMOTEIP}) { - - # 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}; + %info = $self->conn_info_tcpserver(); } else { - # 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 ($port, $iaddr) = sockaddr_in($hersockaddr); - $remote_ip = inet_ntoa($iaddr); - $remote_host = gethostbyaddr($iaddr, AF_INET) || "[$remote_ip]"; - $remote_info = $remote_host; + %info = $self->conn_info_inetd(); } - $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 # ansi escape characters that could make a ps axw do "funny" # 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; 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( - 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, - @_ - ); + $self->SUPER::connection->start(%info, @_); } sub run { From cad4f2b1d6a8b1fb628c15019af3262d389696da Mon Sep 17 00:00:00 2001 From: Matt Simerson Date: Thu, 29 Jan 2015 00:15:43 -0800 Subject: [PATCH 2/2] TcpServer: don't 'use parent Qpsmtpd::Base' it breaks stuff. Instead, grab a base object and use it --- lib/Qpsmtpd/TcpServer.pm | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/Qpsmtpd/TcpServer.pm b/lib/Qpsmtpd/TcpServer.pm index 4cff8ec..95b8a57 100644 --- a/lib/Qpsmtpd/TcpServer.pm +++ b/lib/Qpsmtpd/TcpServer.pm @@ -5,10 +5,12 @@ use POSIX (); use Socket; use lib 'lib'; +use Qpsmtpd::Base; use Qpsmtpd::Constants; -use parent 'Qpsmtpd::Base'; use parent 'Qpsmtpd::SMTP'; +my $base = Qpsmtpd::Base->new(); + my $has_ipv6 = 0; if ( eval { require Socket6; } && @@ -55,7 +57,7 @@ sub conn_info_inetd { my ($r_port, $iaddr) = sockaddr_in($hersockaddr); my $r_ip = inet_ntoa($iaddr); - my ($r_host) = $self->resolve_ptr($r_ip) || "[$r_ip]"; + my ($r_host) = $base->resolve_ptr($r_ip) || "[$r_ip]"; return ( local_ip => '', @@ -193,7 +195,9 @@ sub tcpenv { return $TCPLOCALIP, $TCPREMOTEIP, $TCPREMOTEIP ? "[$ENV{TCPREMOTEIP}]" : "[noip!]"; } - my ($TCPREMOTEHOST) = $self->resolve_ptr($TCPREMOTEIP) || 'Unknown'; + my ($TCPREMOTEHOST) = $base->resolve_ptr($TCPREMOTEIP); + $TCPREMOTEHOST ||= 'Unknown'; + return $TCPLOCALIP, $TCPREMOTEIP, $TCPREMOTEHOST; }