diff --git a/lib/Qpsmtpd/Connection.pm b/lib/Qpsmtpd/Connection.pm index ee5913d..3b9d50b 100644 --- a/lib/Qpsmtpd/Connection.pm +++ b/lib/Qpsmtpd/Connection.pm @@ -1,9 +1,6 @@ package Qpsmtpd::Connection; use strict; -use Sys::Hostname; -use Time::HiRes qw(gettimeofday); - # All of these parameters depend only on the physical connection, # i.e. not on anything sent from the remote machine. Hence, they # are an appropriate set to use for either start() or clone(). Do @@ -18,27 +15,7 @@ my @parameters = qw( relay_client ); -my $SALT_HOST = crypt(hostname, chr(65+rand(57)).chr(65+rand(57))); -$SALT_HOST =~ tr/A-Za-z0-9//cd; - -sub new_id { - my $self = shift; - # Generate unique id - # use gettimeofday for microsec precision - # add in rand() in case gettimeofday clock is slow (e.g. bsd?) - # add in $$ in case srand is set per process - my ($start, $mstart) = gettimeofday(); - my $id = sprintf("%d.%06d.%s.%d.%d", - $start, - $mstart, - $SALT_HOST, - rand(10000), - $$, - ); - $self->{_id} = $id; - -} sub new { my $proto = shift; my $class = ref($proto) || $proto; @@ -61,10 +38,16 @@ sub start { sub id { my $self = shift; - $self->new_id unless $self->{_id}; + $self->{_id} = shift if @_; $self->{_id}; } +sub inc_id { + my $self = shift; + my ($qp_id, $count) = $self->{_id} =~ m/(.+)\.(\d+)/; + $self->{_id} = $qp_id . "." . ++$count; +} + sub clone { my $self = shift; my $new = $self->new(); diff --git a/lib/Qpsmtpd/SMTP.pm b/lib/Qpsmtpd/SMTP.pm index c420215..1b769c6 100644 --- a/lib/Qpsmtpd/SMTP.pm +++ b/lib/Qpsmtpd/SMTP.pm @@ -19,6 +19,8 @@ use Mail::Header (); #use Data::Dumper; use POSIX qw(strftime); use Net::DNS; +use Time::HiRes qw(gettimeofday); +use Sys::Hostname; # this is only good for forkserver # can't set these here, cause forkserver resets them @@ -37,10 +39,20 @@ sub new { my (%commands); @commands{@commands} = ('') x @commands; # this list of valid commands should probably be a method or a set of methods $self->{_commands} = \%commands; - $self; } +sub id { + my $self = shift; + unless ($self->{_id}) { + $self->{_id} = sprintf("%d.%06d.%s.%d", + gettimeofday, + unpack("H*", (gethostbyname(hostname))[4]), + $$); + } + return $self->{_id}; +} + sub command_counter { my $self = shift; $self->{_counter} || 0; @@ -135,16 +147,27 @@ sub transaction { sub reset_transaction { my $self = shift; $self->run_hooks("reset_transaction") if $self->{_transaction}; - return $self->{_transaction} = Qpsmtpd::Transaction->new(); + return $self->{_transaction} = + Qpsmtpd::Transaction->new(id => $self->connection->id . "." . ++$self->{_transaction_count}); } sub connection { my $self = shift; @_ and $self->{_connection} = shift; - return $self->{_connection} || ($self->{_connection} = Qpsmtpd::Connection->new()); + unless ($self->{_connection}) { + $self->{_connection} = Qpsmtpd::Connection->new(); + $self->reset_connection; + } + return $self->{_connection}; } +sub reset_connection { + my $self = shift; + $self->connection->id($self->id . "." . ++$self->{_connection_count}); + $self->{_transaction_count} = 0; + $self->reset_transaction; +} sub helo { my ($self, $line) = @_; diff --git a/lib/Qpsmtpd/Transaction.pm b/lib/Qpsmtpd/Transaction.pm index c91e0d3..96ee87b 100644 --- a/lib/Qpsmtpd/Transaction.pm +++ b/lib/Qpsmtpd/Transaction.pm @@ -22,21 +22,7 @@ sub start { my $class = ref($proto) || $proto; my %args = @_; - # Generate unique id - # use gettimeofday for microsec precision - # add in a sequence in case gettimeofday clock is slow (e.g. alpha) - # add in $$ to provide uniqueness per process/child - my ($start, $mstart) = gettimeofday(); - my $seq = $SEQUENCE_ID++ % 10000; - my $id = sprintf("%d.%06d.%s.%d.%d", - $start, - $mstart, - $SALT_HOST, - $seq, - $$, - ); - - my $self = { _rcpt => [], started => $start, _id => $id }; + my $self = { _rcpt => [], started => time, _id => $args{id} }; bless ($self, $class); return $self; } diff --git a/qpsmtpd-forkserver b/qpsmtpd-forkserver index e8dba3a..d3833f7 100755 --- a/qpsmtpd-forkserver +++ b/qpsmtpd-forkserver @@ -239,7 +239,7 @@ while (1) { # get local/remote hostname, port and ip address my ($port, $iaddr, $lport, $laddr, $nto_iaddr, $nto_laddr) = Qpsmtpd::TcpServer::lrpip($server, $client, $hisaddr); - $qpsmtpd->connection->new_id; + $qpsmtpd->reset_connection; my ($rc, @msg) = $qpsmtpd->run_hooks("pre-connection", remote_ip => $nto_iaddr, remote_port => $port,