Listen on user-specified addresses
authorMegaBrutal <code+git@megabrutal.com>
Fri, 12 Oct 2018 06:05:25 +0000 (08:05 +0200)
committerMegaBrutal <code+git@megabrutal.com>
Fri, 12 Oct 2018 06:05:25 +0000 (08:05 +0200)
Configuration key ListenPort has been changed to ListenAddress.
Now it is possible to supply exact addresses to listen on instead
of all addresses (0.0.0.0). Backward compatibility is kept, so old
ListenPort values will still be interpreted (if no ListenAddress is
present).

ListenPort = 25 ==> ListenAddress = 0.0.0.0:25

Multiple listen addresses may be separated by commas, e.g.
ListenAddress = 192.168.1.161:25,127.0.0.1:225

Port 25 is implied when no port is specified for an address.

modified:   Common.pas
modified:   Listener.pas
modified:   MgSMTP.pas
modified:   Network.pas

Common.pas
Listener.pas
MgSMTP.pas
Network.pas

index 76926728bcbeddd3042f36a2bca0ff8be1e73b50..fadccc59f8b17f0ca294d84740c7af03e946d546 100644 (file)
@@ -1,5 +1,5 @@
 {
-   Copyright (C) 2010-2015 MegaBrutal
+   Copyright (C) 2010-2018 MegaBrutal
 
    This unit is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
@@ -73,10 +73,10 @@ type
       {FTimeCorrection: integer;}
       FTimeOffset: integer;
       FTimeOffsetStr: string;
-      FListenPorts: TStrings;
+      FListenAddresses: TStrings;
    public
       function GetVersionStr: string;
-      property ListenPorts: TStrings read FListenPorts;
+      property ListenAddresses: TStrings read FListenAddresses;
       property Databytes: longint read FDatabytes;
       {property TimeCorrection: integer read FTimeCorrection;}
       property TimeOffset: integer read FTimeOffset;
@@ -465,14 +465,25 @@ begin
 end;
 
 constructor TMainServerConfig.Create(Config: TINIFile);
+var i: integer; rawaddresslist: string; portlist: TStringList;
 begin
    inherited Create(Config.ReadString('Server', 'Name', ''), Config, 'Server');
-   FListenPorts:= TStringList.Create;
-   FListenPorts.Delimiter:= ',';
-   FListenPorts.DelimitedText:= Config.ReadString('Server', 'ListenPort', '25');
+   FListenAddresses:= TStringList.Create;
+   FListenAddresses.Delimiter:= ',';
+
+   rawaddresslist:= Config.ReadString('Server', 'ListenAddress', '');
+   if rawaddresslist <> '' then
+      FListenAddresses.DelimitedText:= rawaddresslist
+   else begin
+      portlist:= TStringList.Create;
+      portlist.Delimiter:= ',';
+      portlist.DelimitedText:= Config.ReadString('Server', 'ListenPort', '25');
+      for i:= 0 to portlist.Count - 1 do
+         FListenAddresses.Add('0.0.0.0:' + portlist.Strings[i]);
+      portlist.Free;
+   end;
 
    FDatabytes:=      Config.ReadInteger('Server', 'Databytes', 1024 * 1024 * 1024);
-   {FTimeCorrection:= Config.ReadInteger('Server', 'TimeCorrection', 0);}
    FTimeOffset:=     Config.ReadInteger('Server', 'TimeOffset', Config.ReadInteger('Server', 'TimeCorrection', 0) * 100);
    FTimeOffsetStr:=  MakeTimeOffsetStr(FTimeOffset);
 
index b37662b15302704304dfaa0ad059ea99ab4337ec..fc92edd86a77c31ac0a808354e03fc3710940c71 100644 (file)
@@ -1,6 +1,6 @@
 {
    MegaBrutal's SMTP Server (MgSMTP)
-   Copyright (C) 2010-2014 MegaBrutal
+   Copyright (C) 2010-2018 MegaBrutal
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
@@ -38,7 +38,7 @@ uses SysUtils, Classes, Base64, Network, NetRFC, RFCSMTP,
 type
 
    TMgSMTPListener = class(TTCPListener)
-      constructor Create(Port: word);
+      constructor Create(const Address: string; Port: word);
    protected
       procedure HandleClient(Connection: TTCPConnection); override;
       procedure ReceiveEMailData(TCP: TTCPRFCConnection; Response: TRFCReply; SpoolObject: TSpoolObjectCreator);
@@ -57,11 +57,12 @@ var
 
 
 procedure StartListeners;
-var i: integer;
+var i: integer; address, port: string;
 begin
-   SetLength(MgSMTPListeners, MainServerConfig.ListenPorts.Count);
+   SetLength(MgSMTPListeners, MainServerConfig.ListenAddresses.Count);
    for i:= 0 to Length(MgSMTPListeners) - 1 do begin
-      MgSMTPListeners[i]:= TMgSMTPListener.Create(StrToIntDef(MainServerConfig.ListenPorts.Strings[i], STANDARD_SMTP_PORT));
+      SplitParameters(MainServerConfig.ListenAddresses.Strings[i], address, port, ':');
+      MgSMTPListeners[i]:= TMgSMTPListener.Create(address, StrToIntDef(port, STANDARD_SMTP_PORT));
       MgSMTPListeners[i].StartListen;
    end;
 end;
@@ -127,11 +128,11 @@ begin
 end;
 
 
-constructor TMgSMTPListener.Create(Port: word);
+constructor TMgSMTPListener.Create(const Address: string; Port: word);
 begin
    { Request connection objects with support for RFC-style commands & responses. }
-   inherited Create(Port, NET_TCP_RFCSUPPORT);
-   Logger.AddLine('Server', 'Listening on port: ' + IntToStr(Port));
+   inherited Create(Address, Port, NET_TCP_RFCSUPPORT);
+   Logger.AddLine('Server', 'Listening on address: ' + Address + ':' + IntToStr(Port));
 end;
 
 
index 1cee11968ec66ea4e05e193e5620f9e3193102da..2fbc6ce69199c010e47968615d6fc165b3d763f8 100644 (file)
@@ -1,6 +1,6 @@
 {
    MegaBrutal's SMTP Server (MgSMTP)
-   Copyright (C) 2010-2016 MegaBrutal
+   Copyright (C) 2010-2018 MegaBrutal
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
@@ -49,7 +49,7 @@ const
      document what bugfix/feature are you testing with the actual build.
      This will be logged to help you differentiate outputs of subsequent
      builds in your logs. If left empty, it won't be added to the logs. }
-   DEVCOMMENT  =  'Catch CTRL-C in user mode';
+   DEVCOMMENT  =  'ListenAddress';
 
 var
 
@@ -246,7 +246,7 @@ end;
 
 begin
    Out.writeln('MegaBrutal''s SMTP Server, version ' + VERSION_STR + ', ' + IntToStr(PLATFORM_BITS) + ' bits');
-   Out.writeln('Copyright (C) 2010-2014 MegaBrutal');
+   Out.writeln('Copyright (C) 2010-2018 MegaBrutal');
    AddDevComment(Out);
    Out.writeln;
 
index 5ef26164939b85795cf4abc85ef5cf93d20ba9f4..10a95f991d3898060489ecfdc31d252c242b81d7 100644 (file)
@@ -1,6 +1,6 @@
 {
    Basic object-oriented network functions
-   Copyright (C) 2010-2014 MegaBrutal
+   Copyright (C) 2010-2018 MegaBrutal
 
    This unit is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
@@ -99,10 +99,11 @@ type
    end;
 
    TTCPListener = class(TThread)
-      constructor Create(Port: word; FeatureRequest: word);
+      constructor Create(const Address: string; Port: word; FeatureRequest: word);
       {destructor Destroy; override;}
    private
       FFeatureRequest: word;
+      FListenAddress: string;
       FListenPort: word;
       FListenSocket: socket;
       sAddr: TSockAddr;
@@ -163,8 +164,9 @@ begin
 end;
 
 
-constructor TTCPListener.Create(Port: word; FeatureRequest: word);
+constructor TTCPListener.Create(const Address: string; Port: word; FeatureRequest: word);
 begin
+   FListenAddress:= Address;
    FListenPort:= Port;
    FFeatureRequest:= FeatureRequest;
    FreeOnTerminate:= false;
@@ -292,12 +294,11 @@ begin
       with sAddr do begin
          sin_family:= af_inet;
          sin_port:= htons(FListenPort);
-         sin_addr.s_addr:= 0;
+         sin_addr:= ResolveHost(FListenAddress);
       end;
       if fpBind(FListenSocket, @sAddr, sizeof(sAddr)) <> -1 then begin
          { It seems the maximum connection value isn't enforced by the
            Free Pascal library, so this 512 is a constant, dummy value. }
-           { TEMPORARY SETTING OF 1 FROM 512! }
          if fpListen(FListenSocket, 512) <> -1 then begin
             Result:= true;
             Start;