[svn:qpsmtpd] rev 464 - trunk

[email protected] 6 Jul 2005 07:50:00 -0000
Newsgroups perl.cvs.qpsmtpd
Message-ID <[email protected]>
Author: aqua
Date: Wed Jul  6 00:50:00 2005
New Revision: 464

Modified:
   trunk/Changes
   trunk/qpsmtpd-forkserver
Log:
Implement listening on multiple local addresses simultaneously, if specified by
more than one --listen-address commandline argument.


Modified: trunk/Changes
==============================================================================
--- trunk/Changes	(original)
+++ trunk/Changes	Wed Jul  6 00:50:00 2005
@@ -1,5 +1,8 @@
 0.31 -
 
+  qpsmtpd-forkserver: --listen-address may now be given more than once, to
+  request listening on multiple local addresses (Devin Carraway)
+
   qpsmtpd-forkserver: add an option for writing a PID file (pjh)
 
   qpsmtpd-forkserver: set auxiliary groups (this is needed for the

Modified: trunk/qpsmtpd-forkserver
==============================================================================
--- trunk/qpsmtpd-forkserver	(original)
+++ trunk/qpsmtpd-forkserver	Wed Jul  6 00:50:00 2005
@@ -20,7 +20,7 @@ $| = 1;
 # Configuration
 my $MAXCONN   = 15;				# max simultaneous connections
 my $PORT      = 2525;				# port number
-my $LOCALADDR = '0.0.0.0';		# ip address to bind to
+my @LOCALADDR;                                  # ip address to bind to
 my $USER      = 'smtpd';		# user to suid to
 my $MAXCONNIP = 5;              # max simultaneous connections from one IP
 my $PID_FILE   = '';
@@ -28,7 +28,9 @@ my $PID_FILE   = '';
 sub usage {
         print <<"EOT";
 usage: qpsmtpd-forkserver [ options ]
- -l, --listen-address addr : listen on a specific address; default 0.0.0.0
+ -l, --listen-address addr : listen on specific address(es); can be specified
+                             multiple times for multiple bindings.  Default is
+			     0.0.0.0 (all interfaces).
  -p, --port P              : listen on a specific port; default 2525
  -c, --limit-connections N : limit concurrent connections to N; default 15
  -u, --user U              : run as a particular user (default 'smtpd')
@@ -39,7 +41,7 @@ EOT
 }
 
 GetOptions('h|help' => \&usage,
-           'l|listen-address=s' => \$LOCALADDR,
+           'l|listen-address=s' => \@LOCALADDR,
            'c|limit-connections=i' => \$MAXCONN,
            'm|max-from-ip=i' => \$MAXCONNIP,
            'p|port=i' => \$PORT,
@@ -49,7 +51,14 @@ GetOptions('h|help' => \&usage,
 
 # detaint the commandline
 if ($PORT =~ /^(\d+)$/) { $PORT = $1 } else { &usage }
-if ($LOCALADDR =~ /^([\d\w\-.]+)$/) { $LOCALADDR = $1 } else { &usage }
+@LOCALADDR = ( '0.0.0.0' ) if !@LOCALADDR;
+for (0..$#LOCALADDR) {
+  if ($LOCALADDR[$_] =~ /^([\d\w\-.]+)$/) {
+    $LOCALADDR[$_] = $1;
+  } else {
+    &usage;
+  }
+}
 if ($USER =~ /^([\w\-]+)$/) { $USER = $1 } else { &usage }
 if ($MAXCONN =~ /^(\d+)$/) { $MAXCONN = $1 } else { &usage }
 
@@ -75,17 +84,20 @@ sub HUNTSMAN {
 $SIG{INT} = \&HUNTSMAN;
 $SIG{TERM} = \&HUNTSMAN;
 
-# establish SERVER socket, bind and listen.
-my $server = IO::Socket::INET->new(LocalPort => $PORT,
-				   LocalAddr => $LOCALADDR,
-                                   Proto     => 'tcp',
-                                   Reuse     => 1,
-                                   Blocking  => 0,
-                                   Listen    => SOMAXCONN )
-  or die "Creating TCP socket $LOCALADDR:$PORT: $!\n";
-IO::Handle::blocking($server, 0);
-my $sel = IO::Select->new();
-$sel->add($server);
+my $select = new IO::Select;
+
+# establish SERVER socket(s), bind and listen.
+for my $listen_addr (@LOCALADDR) {
+  my $server = IO::Socket::INET->new(LocalPort => $PORT,
+                                     LocalAddr => $listen_addr,
+                                     Proto     => 'tcp',
+                                     Reuse     => 1,
+                                     Blocking  => 0,
+                                     Listen    => SOMAXCONN )
+    or die "Creating TCP socket $listen_addr:$PORT: $!\n";
+  IO::Handle::blocking($server, 0);
+  $select->add($server);
+}
 
 if ($PID_FILE) {
   if ($PID_FILE =~ m#^(/[\w\d/\-.]+)$#) { $PID_FILE = $1 } else { &usage }
@@ -145,8 +157,12 @@ while (1) {
     sleep(1);
     next;
   }
-  next unless $sel->can_read(1);
-    my $hisaddr = accept(my $client, $server);
+  my @ready = $select->can_read(1);
+  next if !@ready;
+  my $server = shift @ready;
+
+  my ($client, $hisaddr) = $server->accept;
+
     if (!$hisaddr) {
         # possible something condition...
         next;