]> git.ipfire.org Git - ipfire-2.x.git/blobdiff - html/cgi-bin/guardian.cgi
Merge remote-tracking branch 'origin/master' into next
[ipfire-2.x.git] / html / cgi-bin / guardian.cgi
index 5547ee45179a6a7831cfe2349ac91c0e1da08b8c..6144aca025a71dcf67673b80f9ac96992bfb749d 100644 (file)
@@ -2,7 +2,7 @@
 ###############################################################################
 #                                                                             #
 # IPFire.org - A linux based firewall                                         #
-# Copyright (C) 2014  IPFire Team  <info@ipfire.org>                          #
+# Copyright (C) 2016  IPFire Team  <info@ipfire.org>                          #
 #                                                                             #
 # This program is free software: you can redistribute it and/or modify        #
 # it under the terms of the GNU General Public License as published by        #
 ###############################################################################
 
 use strict;
-use Locale::Country;
+use Locale::Codes::Country;
+use Guardian::Socket;
 
 # enable only the following on debugging purpose
-use warnings;
-use CGI::Carp 'fatalsToBrowser';
+#use warnings;
+#use CGI::Carp 'fatalsToBrowser';
 
 require '/var/ipfire/general-functions.pl';
 require "${General::swroot}/lang.pl";
 require "${General::swroot}/header.pl";
 
 #workaround to suppress a warning when a variable is used only once
-my @dummy = ( ${Header::colouryellow} );
+my @dummy = (
+       ${Header::colourred},
+       ${Header::colourgreen}
+);
+
 undef (@dummy);
 
 my $string=();
@@ -43,6 +48,14 @@ my @guardian=();
 # Path to the guardian.ignore file.
 my $ignorefile ='/var/ipfire/guardian/guardian.ignore';
 
+# Hash which contains the supported modules and the
+# file locations on IPFire systems.
+my %module_file_locations = (
+       "HTTPD" => "/var/log/httpd/error_log",
+       "SNORT" => "/var/log/snort/alert",
+       "SSH" => "/var/log/messages",
+);
+
 our %netsettings = ();
 &General::readhash("${General::swroot}/ethernet/settings", \%netsettings);
 
@@ -51,20 +64,31 @@ our %mainsettings = ();
 &General::readhash("${General::swroot}/main/settings", \%mainsettings);
 &General::readhash("/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color);
 
+# File declarations.
+my $settingsfile = "${General::swroot}/guardian/settings";
+my $ignoredfile = "${General::swroot}/guardian/ignored";
+
+# Create empty settings and ignoredfile if they do not exist yet.
+unless (-e "$settingsfile") { system("touch $settingsfile"); }
+unless (-e "$ignoredfile") { system("touch $ignoredfile"); }
+
 our %settings = ();
+our %ignored  = ();
+
+$settings{'ACTION'} = '';
 
 $settings{'GUARDIAN_ENABLED'} = 'off';
-$settings{'GUARDIAN_ENABLE_SNORT'} = 'on';
-$settings{'GUARDIAN_ENABLE_SSH'} = 'on';
-$settings{'GUARDIAN_ENABLE_HTTPD'} = 'on';
+$settings{'GUARDIAN_MONITOR_SNORT'} = 'on';
+$settings{'GUARDIAN_MONITOR_SSH'} = 'on';
+$settings{'GUARDIAN_MONITOR_HTTPD'} = 'on';
+$settings{'GUARDIAN_MONITOR_OWNCLOUD'} = '';
+$settings{'GUARDIAN_LOG_FACILITY'} = 'syslog';
 $settings{'GUARDIAN_LOGLEVEL'} = 'info';
 $settings{'GUARDIAN_BLOCKCOUNT'} = '3';
 $settings{'GUARDIAN_BLOCKTIME'} = '86400';
+$settings{'GUARDIAN_FIREWALL_ACTION'} = 'DROP';
 $settings{'GUARDIAN_LOGFILE'} = '/var/log/guardian/guardian.log';
-$settings{'GUARDIAN_SNORT_ALERTFILE'} = '/var/log/snort/alert';
-$settings{'GUARDIAN_PRIORITY_LEVEL'} = '3';
-
-$settings{'ACTION'} = '';
+$settings{'GUARDIAN_SNORT_PRIORITY_LEVEL'} = '3';
 
 my $errormessage = '';
 
@@ -75,7 +99,7 @@ my $errormessage = '';
 
 # Check if guardian is running and grab some stats.
 &daemonstats();
-my $pid = @pid[0];
+my $pid = $pid[0];
 
 ## Perform input checks and save settings.
 #
@@ -85,7 +109,7 @@ if ($settings{'ACTION'} eq $Lang::tr{'save'}) {
                        $errormessage = "$Lang::tr{'guardian invalid blocktime'}";
        }
 
-       # Check if the bloccount is valid.
+       # Check if the blockcount is valid.
        unless(($settings{'GUARDIAN_BLOCKCOUNT'} =~ /^\d+$/) && ($settings{'GUARDIAN_BLOCKCOUNT'} ne "0")) {
                        $errormessage = "$Lang::tr{'guardian invalid blockcount'}";
        }
@@ -95,11 +119,6 @@ if ($settings{'ACTION'} eq $Lang::tr{'save'}) {
                $errormessage = "$Lang::tr{'guardian invalid logfile'}";
        }
 
-       # Check input for snort alert file.
-       unless($settings{'GUARDIAN_SNORT_ALERTFILE'} =~ /^[a-zA-Z0-9\.\/]+$/) {
-               $errormessage = "$Lang::tr{'guardian invalid alertfile'}";
-       }
-
        # Only continue if no error message has been set.
        if($errormessage eq '') {
                # Write configuration settings to file.
@@ -109,15 +128,15 @@ if ($settings{'ACTION'} eq $Lang::tr{'save'}) {
                &BuildConfiguration();
        }
 
-## Add a new entry to the ignore file.
+## Add/edit an entry to the ignore file.
 #
-} elsif ($settings{'ACTION'} eq $Lang::tr{'add'}) {
+} elsif (($settings{'ACTION'} eq $Lang::tr{'add'}) || ($settings{'ACTION'} eq $Lang::tr{'update'})) {
 
        # Check if any input has been performed.
-       if ($settings{'NEW_IGNORE_ENTRY'} ne '') {
+       if ($settings{'IGNORE_ENTRY_ADDRESS'} ne '') {
 
                # Check if the given input is no valid IP-address or IP-address with subnet, display an error message.
-               if ((!&General::validip($settings{'NEW_IGNORE_ENTRY'})) && (!&General::validipandmask($settings{'NEW_IGNORE_ENTRY'}))) {
+               if ((!&General::validip($settings{'IGNORE_ENTRY_ADDRESS'})) && (!&General::validipandmask($settings{'IGNORE_ENTRY_ADDRESS'}))) {
                        $errormessage = "$Lang::tr{'guardian invalid address or subnet'}";
                }
        } else {
@@ -126,50 +145,129 @@ if ($settings{'ACTION'} eq $Lang::tr{'save'}) {
 
        # Go further if there was no error.
        if ($errormessage eq '') {
-               my $new_entry = $settings{'NEW_IGNORE_ENTRY'};
+               my %ignored = ();
+               my $id;
+               my $status;
 
-               # Open file for appending the new entry.
-               open (FILE, ">>$ignorefile") or die "Unable to open $ignorefile for writing";
+               # Assign hash values.
+               my $new_entry_address = $settings{'IGNORE_ENTRY_ADDRESS'};
+               my $new_entry_remark = $settings{'IGNORE_ENTRY_REMARK'};
 
-               # Write the new entry to the ignore file.
-               print FILE "$new_entry\n";
-               close(FILE);
+               # Read-in ignoredfile.
+               &General::readhasharray($ignoredfile, \%ignored);
+
+               # Check if we should edit an existing entry and got an ID.
+               if (($settings{'ACTION'} eq $Lang::tr{'update'}) && ($settings{'ID'})) {
+                       # Assin the provided id.
+                       $id = $settings{'ID'};
+
+                       # Undef the given ID.
+                       undef($settings{'ID'});
+
+                       # Grab the configured status of the corresponding entry.
+                       $status = $ignored{$id}[2];
+               } else {
+                       # Each newly added entry automatically should be enabled.
+                       $status = "enabled";
+
+                       # Generate the ID for the new entry.
+                       #
+                       # Sort the keys by their ID and store them in an array.
+                       my @keys = sort { $a <=> $b } keys %ignored;
+
+                       # Reverse the key array.
+                       my @reversed = reverse(@keys);
+
+                       # Obtain the last used id.
+                       my $last_id = @reversed[0];
+
+                       # Increase the last id by one and use it as id for the new entry.
+                       $id = ++$last_id;
+               }
+
+               # Add/Modify the entry to/in the ignored hash.
+               $ignored{$id} = ["$new_entry_address", "$new_entry_remark", "$status"];
+
+               # Write the changed ignored hash to the ignored file.
+               &General::writehasharray($ignoredfile, \%ignored);
+
+               # Regenerate the ignore file.
+               &GenerateIgnoreFile();
        }
 
        # Check if guardian is running.
        if ($pid > 0) {
-               # Call guardianctrl to perform a reload.
-               system("/usr/local/bin/guardianctrl reload &>/dev/null");
+               # Send reload command through socket connection.
+               &Guardian::Socket::Client("reload-ignore-list");
        }
 
-## Remove entry from ignore list.
+## Toggle Enabled/Disabled for an existing entry on the ignore list.
 #
-} elsif ($settings{'ACTION'} eq $Lang::tr{'remove'}) {
-       my $id = 0;
 
-       # Open ignorefile and read content.
-       open(FILE, "<$ignorefile") or die "Unable to open $ignorefile.";
-       my @current = <FILE>;
-       close(FILE);
+} elsif ($settings{'ACTION'} eq $Lang::tr{'toggle enable disable'}) {
+       my %ignored = ();
+
+       # Only go further, if an ID has been passed.
+       if ($settings{'ID'}) {
+               # Assign the given ID.
+               my $id = $settings{'ID'};
+
+               # Undef the given ID.
+               undef($settings{'ID'});
 
-       # Re-open ignorefile for writing.
-       open(FILE, ">$ignorefile") or die "Unable to open $ignorefile for writing";
-       flock FILE, 2;
+               # Read-in ignoredfile.
+               &General::readhasharray($ignoredfile, \%ignored);
 
-       # Read line by line from ignorefile and write them back except the line with the given ID.
-       # So this line is missing in the new file and the entry has been deleted.
-       foreach my $line (@current) {
-               $id++;
-               unless ($settings{'ID'} eq $id) {
-                       print FILE "$line";
+               # Grab the configured status of the corresponding entry.
+               my $status = $ignored{$id}[2];
+
+               # Switch the status.
+               if ($status eq "disabled") {
+                       $status = "enabled";
+               } else {
+                       $status = "disabled";
+               }
+
+               # Modify the status of the existing entry.
+               $ignored{$id} = ["$ignored{$id}[0]", "$ignored{$id}[1]", "$status"];
+
+               # Write the changed ignored hash to the ignored file.
+               &General::writehasharray($ignoredfile, \%ignored);
+
+               # Regenerate the ignore file.
+               &GenerateIgnoreFile();
+
+               # Check if guardian is running.
+               if ($pid > 0) {
+                       # Send reload command through socket connection.
+                       &Guardian::Socket::Client("reload-ignore-list");
                }
        }
-       close(FILE);
+
+## Remove entry from ignore list.
+#
+} elsif ($settings{'ACTION'} eq $Lang::tr{'remove'}) {
+       my %ignored = ();
+
+       # Read-in ignoredfile.
+       &General::readhasharray($ignoredfile, \%ignored);
+
+       # Drop entry from the hash.
+       delete($ignored{$settings{'ID'}});
+
+       # Undef the given ID.
+       undef($settings{'ID'});
+
+       # Write the changed ignored hash to the ignored file.
+       &General::writehasharray($ignoredfile, \%ignored);
+
+       # Regenerate the ignore file.
+       &GenerateIgnoreFile();
 
        # Check if guardian is running.
        if ($pid > 0) {
-               # Call guardianctrl to perform a reload.
-               system("/usr/local/bin/guardianctrl reload &>/dev/null");
+               # Send reload command through socket connection.
+               &Guardian::Socket::Client("reload-ignore-list");
        }
 
 ## Block a user given address or subnet.
@@ -183,8 +281,17 @@ if ($settings{'ACTION'} eq $Lang::tr{'save'}) {
        my $orange = $netsettings{'ORANGE_ADDRESS'};
        my $red = $netsettings{'RED_ADDRESS'};
 
+       # File declarations.
+       my $gatewayfile = "${General::swroot}/red/remote-ipaddress";
+       my $dns1file = "${General::swroot}/red/dns1";
+       my $dns2file = "${General::swroot}/red/dns2";
+
        # Get gateway address.
-       my $gateway = &General::get_gateway();
+       my $gateway = &_get_address_from_file($gatewayfile);
+
+       # Get addresses from the used dns servers.
+       my $dns1 = &_get_address_from_file($dns1file);
+       my $dns2 = &_get_address_from_file($dns2file);
 
        # Check if any input has been performed.
        if ($input eq '') {
@@ -202,7 +309,7 @@ if ($settings{'ACTION'} eq $Lang::tr{'save'}) {
        }
 
        # Check if the given input is one of the interface addresses or our gateway.
-       elsif ($input eq "$green" || $input eq "$blue" || $input eq "$orange" || $input eq "$red" || $input eq "$gateway") {
+       elsif ($input eq "$green" || $input eq "$blue" || $input eq "$orange" || $input eq "$red" || $input eq "$gateway" || $input eq "$dns1" || $input eq "$dns2") {
                $errormessage = "$Lang::tr{'guardian blocking of this address is not allowed'}";
        }
 
@@ -215,8 +322,8 @@ if ($settings{'ACTION'} eq $Lang::tr{'save'}) {
         if ($errormessage eq '') {
                 my $block = $settings{'ADDRESS_BLOCK'};
 
-                # Call helper to unblock address.
-                system("/usr/local/bin/guardianctrl block $block &>/dev/null");
+               # Send command to block the specified address through socket connection.
+               &Guardian::Socket::Client("block $block");
         }
 
 ## Unblock address or subnet.
@@ -239,20 +346,21 @@ if ($settings{'ACTION'} eq $Lang::tr{'save'}) {
        if ($errormessage eq '') {
                 my $unblock = $settings{'ADDRESS_UNBLOCK'};
 
-               # Call helper to unblock address.
-               system("/usr/local/bin/guardianctrl unblock $unblock &>/dev/null");
+               # Send command to unblock the given address through socket connection.
+               &Guardian::Socket::Client("unblock $unblock");
        }
 
 ## Unblock all.
 #
 } elsif ($settings{'ACTION'} eq $Lang::tr{'unblock all'}) {
 
-       # Call helper to flush iptables chain from guardian.
-       system("/usr/local/bin/guardianctrl flush-chain &>/dev/null");
+       # Send flush command through socket connection.
+       &Guardian::Socket::Client("flush");
 }
 
-# Load settings from file.
+# Load settings from files.
 &General::readhash("${General::swroot}/guardian/settings", \%settings);
+&General::readhasharray("${General::swroot}/guardian/ignored", \%ignored);
 
 # Call functions to generate whole page.
 &showMainBox();
@@ -271,18 +379,23 @@ sub showMainBox() {
        $checked{'GUARDIAN_ENABLED'}{'on'} = '';
        $checked{'GUARDIAN_ENABLED'}{'off'} = '';
        $checked{'GUARDIAN_ENABLED'}{$settings{'GUARDIAN_ENABLED'}} = 'checked';
-       $checked{'GUARDIAN_ENABLE_SNORT'}{'off'} = '';
-       $checked{'GUARDIAN_ENABLE_SNORT'}{'on'} = '';
-       $checked{'GUARDIAN_ENABLE_SNORT'}{$settings{'GUARDIAN_ENABLE_SNORT'}} = "checked='checked'";
-       $checked{'GUARDIAN_ENABLE_SSH'}{'off'} = '';
-       $checked{'GUARDIAN_ENABLE_SSH'}{'on'} = '';
-       $checked{'GUARDIAN_ENABLE_SSH'}{$settings{'GUARDIAN_ENABLE_SSH'}} = "checked='checked'";
-       $checked{'GUARDIAN_ENABLE_HTTPD'}{'off'} = '';
-       $checked{'GUARDIAN_ENABLE_HTTPD'}{'on'} = '';
-       $checked{'GUARDIAN_ENABLE_HTTPD'}{$settings{'GUARDIAN_ENABLE_HTTPD'}} = "checked='checked'";
-
+       $checked{'GUARDIAN_MONITOR_SNORT'}{'off'} = '';
+       $checked{'GUARDIAN_MONITOR_SNORT'}{'on'} = '';
+       $checked{'GUARDIAN_MONITOR_SNORT'}{$settings{'GUARDIAN_MONITOR_SNORT'}} = "checked='checked'";
+       $checked{'GUARDIAN_MONITOR_SSH'}{'off'} = '';
+       $checked{'GUARDIAN_MONITOR_SSH'}{'on'} = '';
+       $checked{'GUARDIAN_MONITOR_SSH'}{$settings{'GUARDIAN_MONITOR_SSH'}} = "checked='checked'";
+       $checked{'GUARDIAN_MONITOR_HTTPD'}{'off'} = '';
+       $checked{'GUARDIAN_MONITOR_HTTPD'}{'on'} = '';
+       $checked{'GUARDIAN_MONITOR_HTTPD'}{$settings{'GUARDIAN_MONITOR_HTTPD'}} = "checked='checked'";
+       $checked{'GUARDIAN_MONITOR_OWNCLOUD'}{'off'} = '';
+       $checked{'GUARDIAN_MONITOR_OWNCLOUD'}{'on'} = '';
+       $checked{'GUARDIAN_MONITOR_OWNCLOUD'}{$settings{'GUARDIAN_MONITOR_OWNCLOUD'}} = "checked='checked'";
+
+       $selected{'GUARDIAN_LOG_FACILITY'}{$settings{'GUARDIAN_LOG_FACILITY'}} = 'selected';
        $selected{'GUARDIAN_LOGLEVEL'}{$settings{'GUARDIAN_LOGLEVEL'}} = 'selected';
-       $selected{'GUARDIAN_PRIORITY_LEVEL'}{$settings{'GUARDIAN_PRIORITY_LEVEL'}} = 'selected';
+       $selected{'GUARDIAN_SNORT_PRIORITY_LEVEL'}{$settings{'GUARDIAN_SNORT_PRIORITY_LEVEL'}} = 'selected';
+       $selected{'GUARDIAN_FIREWALL_ACTION'}{$settings{'GUARDIAN_FIREWALL_ACTION'}} = 'selected';
 
        &Header::openpage($Lang::tr{'guardian configuration'}, 1, '');
        &Header::openbigbox('100%', 'left', '', $errormessage);
@@ -294,13 +407,71 @@ sub showMainBox() {
                &Header::closebox();
        }
 
+       ### Java Script ###
+       print<<END;
+       <script>
+               var update_options = function() {
+
+                       var logfacility = \$("#GUARDIAN_LOG_FACILITY").val();
+                       var loglevel = \$("#GUARDIAN_LOGLEVEL").val();
+
+                       if (logfacility === undefined)
+                               return;
+
+                       if (loglevel === undefined)
+                               return;
+
+                       // Show / Hide input for specifying the path to the logfile.
+                       if (logfacility === "file") {
+                               \$(".GUARDIAN_LOGFILE").show();
+                       } else {
+                               \$(".GUARDIAN_LOGFILE").hide();
+                       }
+
+                       // Show / Hide loglevel debug if the facility is set to syslog.
+                       if (logfacility === "syslog") {
+                               \$("#loglevel_debug").hide();
+                       } else {
+                               \$("#loglevel_debug").show();
+                       }
+
+                       // Show / Hide logfacility syslog if the loglevel is set to debug.
+                       if (loglevel === "debug") {
+                               \$("#logfacility_syslog").hide();
+                       } else {
+                               \$("#logfacility_syslog").show();
+                       }
+               };
+
+               \$(document).ready(function() {
+                       \$("#GUARDIAN_LOG_FACILITY").change(update_options);
+                       \$("#GUARDIAN_LOGLEVEL").change(update_options);
+                       update_options();
+
+                       // Show / Hide snort priority level option, based if
+                       // snort is enabled / disabled.
+                       if (\$('input[name=GUARDIAN_MONITOR_SNORT]:checked').val() == 'on') {
+                               \$('.GUARDIAN_SNORT_PRIORITY_LEVEL').show();
+                       } else {
+                               \$('.GUARDIAN_SNORT_PRIORITY_LEVEL').hide();
+                       }
+
+                       // Show/Hide snort priority level when GUARDIAN_MONITOR_SNORT get changed.
+                       \$('input[name=GUARDIAN_MONITOR_SNORT]').change(function() {
+                               \$('.GUARDIAN_SNORT_PRIORITY_LEVEL').toggle();
+                       });
+               });
+       </script>
+END
+
+
 
        # Draw current guardian state.
        &Header::openbox('100%', 'center', $Lang::tr{'guardian'});
 
        # Get current status of guardian.
        &daemonstats();
-       $pid = @pid[0];
+       $pid = $pid[0];
 
        # Display some useful information related to guardian, if daemon is running.
        if ( ($memory != 0) && ($pid > 0) ){
@@ -320,7 +491,7 @@ sub showMainBox() {
                                </tr>
                                <tr>
                                        <td class='base'></td>
-                                       <td bgcolor='$color{'color22'}' align='center'>@pid[0]</td>
+                                       <td bgcolor='$color{'color22'}' align='center'>$pid</td>
                                        <td bgcolor='$color{'color22'}' align='center'>$memory KB</td>
                                </tr>
                        </table>
@@ -352,70 +523,95 @@ END
                        <tr>
                                <td colspan='2' class='base' bgcolor='$color{'color20'}'><b>$Lang::tr{'guardian common settings'}</b></td>
                        </tr>
+
                        <tr>
-                               <td width='20%' class='base'>$Lang::tr{'guardian enabled'}:</td>
+                               <td width='25%' class='base'>$Lang::tr{'guardian enabled'}:</td>
                                <td><input type='checkbox' name='GUARDIAN_ENABLED' $checked{'GUARDIAN_ENABLED'}{'on'} /></td>
                        </tr>
+
                        <tr>
                                <td colspan='2'><br></td>
                        </tr>
+
                        <tr>
-                               <td width='20%' class='base'>$Lang::tr{'guardian watch snort alertfile'}</td>
-                               <td align='left'>on <input type='radio' name='GUARDIAN_ENABLE_SNORT' value='on' $checked{'GUARDIAN_ENABLE_SNORT'}{'on'} /> /
-                               <input type='radio' name='GUARDIAN_ENABLE_SNORT' value='off' $checked{'GUARDIAN_ENABLE_SNORT'}{'off'} /> off</td>
+                               <td width='25%' class='base'>$Lang::tr{'guardian watch snort alertfile'}</td>
+                               <td align='left'>on <input type='radio' name='GUARDIAN_MONITOR_SNORT' value='on' $checked{'GUARDIAN_MONITOR_SNORT'}{'on'} /> /
+                               <input type='radio' name='GUARDIAN_MONITOR_SNORT' value='off' $checked{'GUARDIAN_MONITOR_SNORT'}{'off'} /> off</td>
                        </tr>
+
                        <tr>
-                               <td width='20%' class='base'>$Lang::tr{'guardian block ssh brute-force'}</td>
-                               <td align='left'>on <input type='radio' name='GUARDIAN_ENABLE_SSH' value='on' $checked{'GUARDIAN_ENABLE_SSH'}{'on'} /> /
-                               <input type='radio' name='GUARDIAN_ENABLE_SSH' value='off' $checked{'GUARDIAN_ENABLE_SSH'}{'off'} /> off</td>
+                               <td width='25%' class='base'>$Lang::tr{'guardian block ssh brute-force'}</td>
+                               <td align='left'>on <input type='radio' name='GUARDIAN_MONITOR_SSH' value='on' $checked{'GUARDIAN_MONITOR_SSH'}{'on'} /> /
+                               <input type='radio' name='GUARDIAN_MONITOR_SSH' value='off' $checked{'GUARDIAN_MONITOR_SSH'}{'off'} /> off</td>
                        </tr>
+
                        <tr>
-                               <td width='20%' class='base'>$Lang::tr{'guardian block httpd brute-force'}</td>
-                               <td align='left'>on <input type='radio' name='GUARDIAN_ENABLE_HTTPD' value='on' $checked{'GUARDIAN_ENABLE_HTTPD'}{'on'} /> /
-                               <input type='radio' name='GUARDIAN_ENABLE_HTTPD' value='off' $checked{'GUARDIAN_ENABLE_HTTPD'}{'off'} /> off</td>
+                               <td width='25%' class='base'>$Lang::tr{'guardian block httpd brute-force'}</td>
+                               <td align='left'>on <input type='radio' name='GUARDIAN_MONITOR_HTTPD' value='on' $checked{'GUARDIAN_MONITOR_HTTPD'}{'on'} /> /
+                               <input type='radio' name='GUARDIAN_MONITOR_HTTPD' value='off' $checked{'GUARDIAN_MONITOR_HTTPD'}{'off'} /> off</td>
                        </tr>
+
                        <tr>
                                <td colspan='2'><br></td>
                        </tr>
+
                        <tr>
+                               <td align='left' width='20%'>$Lang::tr{'guardian logfacility'}:</td>
+                               <td width='25%'><select id='GUARDIAN_LOG_FACILITY' name='GUARDIAN_LOG_FACILITY'>
+                                       <option id='logfacility_syslog' value='syslog' $selected{'GUARDIAN_LOG_FACILITY'}{'syslog'}>$Lang::tr{'guardian logtarget_syslog'}</option>
+                                       <option id='logfacility_file' value='file' $selected{'GUARDIAN_LOG_FACILITY'}{'file'}>$Lang::tr{'guardian logtarget_file'}</option>
+                                       <option id='logfacility_console' value='console' $selected{'GUARDIAN_LOG_FACILITY'}{'console'}>$Lang::tr{'guardian logtarget_console'}</option>
+                               </select></td>
+
                                <td align='left' width='20%'>$Lang::tr{'guardian loglevel'}:</td>
-                               <td><select name='GUARDIAN_LOGLEVEL'>
-                                       <option value='off' $selected{'GUARDIAN_LOGLEVEL'}{'off'}>off</option>
-                                       <option value='info' $selected{'GUARDIAN_LOGLEVEL'}{'info'}>info</option>
-                                       <option value='debug' $selected{'GUARDIAN_LOGLEVEL'}{'debug'}>debug</option>
+                               <td width='25%'><select id='GUARDIAN_LOGLEVEL' name='GUARDIAN_LOGLEVEL'>
+                                       <option id='loglevel_off' value='off' $selected{'GUARDIAN_LOGLEVEL'}{'off'}>$Lang::tr{'guardian loglevel_off'}</option>
+                                       <option id='loglevel_info' value='info' $selected{'GUARDIAN_LOGLEVEL'}{'info'}>$Lang::tr{'guardian loglevel_info'}</option>
+                                       <option id='loglevel_debug' value='debug' $selected{'GUARDIAN_LOGLEVEL'}{'debug'}>$Lang::tr{'guardian loglevel_debug'}</option>
                                </select></td>
                        </tr>
-                       <tr>
+
+                       <tr class="GUARDIAN_LOGFILE">
                                <td colspan='2'><br></td>
                        </tr>
-                       <tr>
+
+                       <tr class="GUARDIAN_LOGFILE">
+                               <td width='25%' class='base'>$Lang::tr{'guardian logfile'}:</td>
+                               <td><input type='text' name='GUARDIAN_LOGFILE' value='$settings{'GUARDIAN_LOGFILE'}' size='30' /></td>
+                       </tr>
+
+                       <tr class="GUARDIAN_SNORT_PRIORITY_LEVEL">
+                               <td colspan='2'><br></td>
+                       </tr>
+
+                       <tr class="GUARDIAN_SNORT_PRIORITY_LEVEL">
                                <td align='left' width='20%'>$Lang::tr{'guardian priority level'}:</td>
-                               <td><select name='GUARDIAN_PRIORITY_LEVEL'>
-                                       <option value='1' $selected{'GUARDIAN_PRIORITY_LEVEL'}{'1'}>1</option>
-                                       <option value='2' $selected{'GUARDIAN_PRIORITY_LEVEL'}{'2'}>2</option>
-                                       <option value='3' $selected{'GUARDIAN_PRIORITY_LEVEL'}{'3'}>3</option>
-                                       <option value='4' $selected{'GUARDIAN_PRIORITY_LEVEL'}{'4'}>4</option>
+                               <td><select name='GUARDIAN_SNORT_PRIORITY_LEVEL'>
+                                       <option value='1' $selected{'GUARDIAN_SNORT_PRIORITY_LEVEL'}{'1'}>$Lang::tr{'guardian priolevel_high'}</option>
+                                       <option value='2' $selected{'GUARDIAN_SNORT_PRIORITY_LEVEL'}{'2'}>$Lang::tr{'guardian priolevel_medium'}</option>
+                                       <option value='3' $selected{'GUARDIAN_SNORT_PRIORITY_LEVEL'}{'3'}>$Lang::tr{'guardian priolevel_low'}</option>
+                                       <option value='4' $selected{'GUARDIAN_SNORT_PRIORITY_LEVEL'}{'4'}>$Lang::tr{'guardian priolevel_very_low'}</option>
                                </select></td>
+
+                               <td width='25%' class='base'>$Lang::tr{'guardian blockcount'}:</td>
+                               <td><input type='text' name='GUARDIAN_BLOCKCOUNT' value='$settings{'GUARDIAN_BLOCKCOUNT'}' size='5' /></td>
                        </tr>
+
                        <tr>
                                <td colspan='2'><br></td>
                        </tr>
+
                        <tr>
-                               <td width='20%' class='base'>$Lang::tr{'guardian blockcount'}:</td>
-                               <td><input type='text' name='GUARDIAN_BLOCKCOUNT' value='$settings{'GUARDIAN_BLOCKCOUNT'}' size='5' /></td>
-                       </tr>
-                       <tr>
-                               <td width='20%' class='base'>$Lang::tr{'guardian blocktime'}:</td>
+                               <td width='25%' class='base'>$Lang::tr{'guardian firewallaction'}:</td>
+                               <td><select name='GUARDIAN_FIREWALL_ACTION'>
+                                       <option value='DROP' $selected{'GUARDIAN_FIREWALL_ACTION'}{'DROP'}>Drop</option>
+                                       <option value='REJECT' $selected{'GUARDIAN_FIREWALL_ACTION'}{'REJECT'}>Reject</option>
+                               </select></td>
+
+                               <td width='25%' class='base'>$Lang::tr{'guardian blocktime'}:</td>
                                <td><input type='text' name='GUARDIAN_BLOCKTIME' value='$settings{'GUARDIAN_BLOCKTIME'}' size='10' /></td>
                        </tr>
-                       <tr>
-                                <td width='20%' class='base'>$Lang::tr{'guardian logfile'}:</td>
-                                <td><input type='text' name='GUARDIAN_LOGFILE' value='$settings{'GUARDIAN_LOGFILE'}' size='30' /></td>
-                        </tr>
-                        <tr>
-                                <td width='20%' class='base'>$Lang::tr{'guardian snort alertfile'}:</td>
-                                <td><input type='text' name='GUARDIAN_SNORT_ALERTFILE' value='$settings{'GUARDIAN_SNORT_ALERTFILE'}' size='30' /></td>
-                        </tr>
+
                </table>
 END
 
@@ -440,49 +636,79 @@ sub showIgnoreBox() {
         &Header::openbox('100%', 'center', $Lang::tr{'guardian ignored hosts'});
 
        print <<END;
-               <table width='60%'>
+               <table width='80%'>
                        <tr>
-                               <td colspan='2' class='base' bgcolor='$color{'color20'}'><b>$Lang::tr{'guardian ignored hosts'}</b></td>
+                               <td class='base' bgcolor='$color{'color20'}'><b>$Lang::tr{'ip address'}</b></td>
+                               <td class='base' bgcolor='$color{'color20'}'><b>$Lang::tr{'remark'}</b></td>
+                               <td class='base' colspan='3' bgcolor='$color{'color20'}'></td>
                        </tr>
 END
-                       # Check if the guardian ignore file contains any content.
-                       if (-s $ignorefile) {
-
-                               # Open file and print contents.
-                               open FILE, $ignorefile or die "Could not open $ignorefile";
-
-                               my $id = 0;
+                       # Check if some hosts have been added to be ignored.
+                       if (keys (%ignored)) {
                                my $col = "";
 
-                               # Read file line by line and print out the elements.
-                               while( my $ignored_element = <FILE> )  {
-
-                                       # Increase id number for each element in the ignore file.
-                                       $id++;
-
-                                       # Check if the id number is even or not.
-                                       if ($id % 2) {
+                               # Loop through all entries of the hash.
+                               while( (my $key) = each %ignored)  {
+                                       # Assign data array positions to some nice variable names.
+                                       my $address = $ignored{$key}[0];
+                                       my $remark = $ignored{$key}[1];
+                                       my $status  = $ignored{$key}[2];
+
+                                       # Check if the key (id) number is even or not.
+                                       if ($settings{'ID'} eq $key) {
+                                               $col="bgcolor='${Header::colouryellow}'";
+                                       } elsif ($key % 2) {
                                                $col="bgcolor='$color{'color22'}'";
                                        } else {
                                                $col="bgcolor='$color{'color20'}'";
                                        }
 
+                                       # Choose icon for the checkbox.
+                                       my $gif;
+                                       my $gdesc;
+
+                                       # Check if the status is enabled and select the correct image and description.
+                                       if ($status eq 'enabled' ) {
+                                               $gif = 'on.gif';
+                                               $gdesc = $Lang::tr{'click to disable'};
+                                       } else {
+                                               $gif = 'off.gif';
+                                               $gdesc = $Lang::tr{'click to enable'};
+                                       }
+
                                        print <<END;
                                        <tr>
-                                               <td width='80%' class='base' $col>$ignored_element</td>
-                                               <td width='20%' align='center' $col>
-                                                       <form method='post' name='$id' action='$ENV{'SCRIPT_NAME'}'>
+                                               <td width='20%' class='base' $col>$address</td>
+                                               <td width='65%' class='base' $col>$remark</td>
+
+                                               <td align='center' $col>
+                                                       <form method='post' action='$ENV{'SCRIPT_NAME'}'>
+                                                               <input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
+                                                               <input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' />
+                                                               <input type='hidden' name='ID' value='$key' />
+                                                       </form>
+                                               </td>
+
+                                               <td align='center' $col>
+                                                       <form method='post' action='$ENV{'SCRIPT_NAME'}'>
+                                                               <input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' />
+                                                               <input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
+                                                               <input type='hidden' name='ID' value='$key' />
+                                                       </form>
+                                               </td>
+
+                                               <td align='center' $col>
+                                                       <form method='post' name='$key' action='$ENV{'SCRIPT_NAME'}'>
                                                                <input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' title='$Lang::tr{'remove'}' alt='$Lang::tr{'remove'}'>
-                                                               <input type='hidden' name='ID' value='$id'>
+                                                               <input type='hidden' name='ID' value='$key'>
                                                                <input type='hidden' name='ACTION' value='$Lang::tr{'remove'}'>
                                                        </form>
                                                </td>
                                        </tr>
 END
                                }
-                       close (FILE);
                        } else {
-                               # Print notice that currently no elements are stored in the ignore file.
+                               # Print notice that currently no hosts are ignored.
                                print "<tr>\n";
                                print "<td class='base' colspan='2'>$Lang::tr{'guardian no entries'}</td>\n";
                                print "</tr>\n";
@@ -490,16 +716,44 @@ END
 
                print "</table>\n";
 
-       # Section to add new elements to the ignore list.
+       # Section to add new elements or edit existing ones.
        print <<END;
        <br>
+       <hr>
+       <br>
+
        <div align='center'>
-               <table width='60%'>
+               <table width='100%'>
+END
+
+       # Assign correct headline and button text.
+       my $buttontext;
+       my $entry_address;
+       my $entry_remark;
+
+       # Check if an ID (key) has been given, in this case an existing entry should be edited.
+       if ($settings{'ID'} ne '') {
+               $buttontext = $Lang::tr{'update'};
+               print "<tr><td class='boldbase' colspan='3'><b>$Lang::tr{'update'}</b></td></tr>\n";
+
+               # Grab address and remark for the given key.
+               $entry_address = $ignored{$settings{'ID'}}[0];
+               $entry_remark = $ignored{$settings{'ID'}}[1];
+       } else {
+               $buttontext = $Lang::tr{'add'};
+               print "<tr><td class='boldbase' colspan='3'><b>$Lang::tr{'dnsforward add a new entry'}</b></td></tr>\n";
+       }
+
+       print <<END;
                        <form method='post' action='$ENV{'SCRIPT_NAME'}'>
+                       <input type='hidden' name='ID' value='$settings{'ID'}'>
                        <tr>
-                               <td width='30%'>$Lang::tr{'dnsforward add a new entry'}: </td>
-                               <td width='50%'><input type='text' name='NEW_IGNORE_ENTRY' value='' size='24' /></td>
-                               <td align='center' width='20%'><input type='submit' name='ACTION' value='$Lang::tr{'add'}' /></td>
+                               <td width='30%'>$Lang::tr{'ip address'}: </td>
+                               <td width='50%'><input type='text' name='IGNORE_ENTRY_ADDRESS' value='$entry_address' size='24' /></td>
+
+                               <td width='30%'>$Lang::tr{'remark'}: </td>
+                               <td wicth='50%'><input type='text' name=IGNORE_ENTRY_REMARK value='$entry_remark' size='24' /></td>
+                               <td align='center' width='20%'><input type='submit' name='ACTION' value='$buttontext' /></td>
                        </tr>
                        </form>
                </table>
@@ -509,7 +763,7 @@ END
        &Header::closebox();
 }
 
-# Function to list currently bocked addresses from guardian and unblock them or add custom entries to block.
+# Function to list currently blocked addresses from guardian and unblock them or add custom entries to block.
 sub showBlockedBox() {
        &Header::openbox('100%', 'center', $Lang::tr{'guardian blocked hosts'});
 
@@ -520,7 +774,7 @@ sub showBlockedBox() {
                </tr>
 END
 
-               # Lauch function to get the currently blocked hosts.
+               # Launch function to get the currently blocked hosts.
                my @blocked_hosts = &GetBlockedHosts();
 
                my $id = 0;
@@ -553,7 +807,7 @@ END
 END
                }
 
-       # If the loop only has been runs once the id still is "0", which means there are no
+       # If the loop only has been run once the id still is "0", which means there are no
        # additional entries (blocked hosts) in the iptables chain.
        if ($id == 0) {
 
@@ -612,31 +866,50 @@ sub daemonstats() {
 }
 
 sub GetBlockedHosts() {
-
        # Create new, empty array.
        my @hosts;
 
-       # Lauch helper to get chains from iptables.
-       open(FILE, "/usr/local/bin/guardianctrl get-chain |");
+       # Launch helper to get chains from iptables.
+       system('/usr/local/bin/getipstat');
+
+       # Open temporary file which contains the chains and rules.
+       open (FILE, '/var/tmp/iptables.txt');
 
-       # Read file line by line and print out the elements.
-       foreach my $line (<FILE>) {
+       # Loop through the entire file.
+       while (<FILE>) {
+               my $line = $_;
 
-               # Skip descriptive lines.
-               next if ($line =~ /^Chain/);
-               next if ($line =~ /^ pkts/);
+               # Search for the guardian chain and extract
+               # the lines between it and the next empty line
+               # which is placed before the next firewall
+               # chain starts.
+               if ($line =~ /^Chain GUARDIAN/ .. /^\s*$/) {
+                       # Skip descriptive lines.
+                       next if ($line =~ /^Chain/);
+                       next if ($line =~ /^ pkts/);
 
-               # Generate array, based on the line content (seperator is a single or multiple space's)
-               my @comps = split(/\s{1,}/, $line);
-               my ($lead, $pkts, $bytes, $target, $prot, $opt, $in, $out, $source, $destination) = @comps;
+                       # Generate array, based on the line content (separator is a single or multiple space)
+                       my @comps = split(/\s{1,}/, $line);
+                       my ($lead, $pkts, $bytes, $target, $prot, $opt, $in, $out, $source, $destination) = @comps;
 
-               # Assign different variable names.
-               my $blocked_host = $source;
+                       # Assign different variable names.
+                       my $blocked_host = $source;
 
-               # Add host to our hosts array.
-               push(@hosts, $blocked_host);
+                       # Add host to our hosts array.
+                       if ($blocked_host) {
+                               push(@hosts, $blocked_host);
+                       }
+               }
        }
 
+       # Close filehandle.
+       close(FILE);
+
+       # Remove recently created temporary files of the "getipstat" binary.
+       system("rm -f /var/tmp/iptables.txt");
+       system("rm -f /var/tmp/iptablesmangle.txt");
+       system("rm -f /var/tmp/iptablesnat.txt");
+
        # Convert entries, sort them, write back and store the sorted entries into new array.
        my @sorted = map  { $_->[0] }
              sort { $a->[1] <=> $b->[1] }
@@ -653,37 +926,191 @@ sub BuildConfiguration() {
 
        my $configfile = "${General::swroot}/guardian/guardian.conf";
 
-       # We set this to 1 (enabled) to prevent guardian from blocking the ISP gateway.
-       my $HostGatewayByte = "1";
+       # Create the configfile if none exists yet.
+       unless (-e "$configfile") { system("touch $configfile"); }
 
        # Open configfile for writing.
        open(FILE, ">$configfile");
 
-       print FILE "EnableSnortMonitoring\t\t$settings{'GUARDIAN_ENABLE_SNORT'}\n";
-       print FILE "EnableSSHMonitoring\t\t$settings{'GUARDIAN_ENABLE_SSH'}\n";
-       print FILE "EnableHTTPDMonitoring\t\t$settings{'GUARDIAN_ENABLE_HTTPD'}\n";
-       print FILE "LogLevel\t\t\t$settings{'GUARDIAN_LOGLEVEL'}\n";
-       print FILE "BlockCount\t\t\t$settings{'GUARDIAN_BLOCKCOUNT'}\n";
-       print FILE "HostGatewayByte\t\t\t$HostGatewayByte\n";
-       print FILE "LogFile\t\t\t\t$settings{'GUARDIAN_LOGFILE'}\n";
-       print FILE "AlertFile\t\t\t$settings{'GUARDIAN_SNORT_ALERTFILE'}\n";
-       print FILE "IgnoreFile\t\t\t$ignorefile\n";
-       print FILE "TimeLimit\t\t\t$settings{'GUARDIAN_BLOCKTIME'}\n";
-       print FILE "PriorityLevel\t\t\t$settings{'GUARDIAN_PRIORITY_LEVEL'}\n";
+       # Config file header.
+       print FILE "# Autogenerated configuration file.\n";
+       print FILE "# All user modifications will be overwritten.\n\n";
+
+       # Settings for the logging mechanism.
+       print FILE "# Log settings.\n";
+       print FILE "LogFacility = $settings{'GUARDIAN_LOG_FACILITY'}\n";
+
+       if ($settings{'GUARDIAN_LOG_FACILITY'} eq "file") {
+               print FILE "LogFile = $settings{'GUARDIAN_LOGFILE'}\n";
+       }
+
+       print FILE "LogLevel = $settings{'GUARDIAN_LOGLEVEL'}\n\n";
+
+       # IPFire related static settings.
+       print FILE "# IPFire related settings.\n";
+       print FILE "FirewallEngine = IPtables\n";
+       print FILE "SocketOwner = nobody:nobody\n";
+       print FILE "IgnoreFile = $ignorefile\n\n";
+
+       # Configured block values.
+       print FILE "# Configured block settings.\n";
+       print FILE "BlockCount = $settings{'GUARDIAN_BLOCKCOUNT'}\n";
+       print FILE "BlockTime = $settings{'GUARDIAN_BLOCKTIME'}\n";
+       print FILE "FirewallAction = $settings{'GUARDIAN_FIREWALL_ACTION'}\n\n";
+
+       # Enabled modules.
+       # Loop through whole settings hash.
+       print FILE "# Enabled modules.\n";
+       foreach my $option (keys %settings) {
+               # Search for enabled modules.
+               if ($option =~ /GUARDIAN_MONITOR_(.*)/) {
+                       # Skip if module is not enabled.
+                       next unless($settings{$option} eq "on");
+
+                       # Skip module if no file location is available.
+                       next unless(exists($module_file_locations{$1}));
+
+                       # Add enabled module and defined path to the config file.
+                       print FILE "Monitor_$1 = $module_file_locations{$1}\n";
+               }
+       }
+
+       # Module settings.
+       print FILE "\n# Module settings.\n";
+       # Check if SNORT is enabled and add snort priority.
+       if ($settings{'GUARDIAN_MONITOR_SNORT'} eq "on") {
+               print FILE "SnortPriorityLevel = $settings{'GUARDIAN_SNORT_PRIORITY_LEVEL'}\n";
+       }
 
        close(FILE);
 
+       # Generate ignore file.
+       &GenerateIgnoreFile();
+
        # Check if guardian should be started or stopped.
        if($settings{'GUARDIAN_ENABLED'} eq 'on') {
                if($pid > 0) {
-                       # Call guardianctl to perform a reload.
-                       system("/usr/local/bin/guardianctrl reload &>/dev/null");
+                       # Send reload command through socket connection.
+                       &Guardian::Socket::Client("reload");
                } else {
                        # Launch guardian.
-                       system("/usr/local/bin/guardianctrl start &>/dev/null");
+                       system("/usr/local/bin/addonctrl guardian start &>/dev/null");
                }
        } else {
                # Stop the daemon.
-               system("/usr/local/bin/guardianctrl stop &>/dev/null");
+               system("/usr/local/bin/addonctrl guardian stop &>/dev/null");
        }
 }
+
+sub GenerateIgnoreFile() {
+       my %ignored = ();
+
+       # Read-in ignoredfile.
+       &General::readhasharray($ignoredfile, \%ignored);
+
+       # Create the guardian.ignore file if not exist yet.
+       unless (-e "$ignorefile") { system("touch $ignorefile"); }
+
+       # Open ignorefile for writing.
+       open(FILE, ">$ignorefile");
+
+       # Config file header.
+       print FILE "# Autogenerated configuration file.\n";
+       print FILE "# All user modifications will be overwritten.\n\n";
+
+       # Add IFPire interfaces and gateway to the ignore file.
+       #
+       # Assign some temporary variables for the IPFire interfaces.
+       my $green = $netsettings{'GREEN_ADDRESS'};
+       my $blue = $netsettings{'BLUE_ADDRESS'};
+       my $orange = $netsettings{'ORANGE_ADDRESS'};
+
+       # File declarations.
+       my $public_address_file = "${General::swroot}/red/local-ipaddress";
+       my $gatewayfile = "${General::swroot}/red/remote-ipaddress";
+       my $dns1file = "${General::swroot}/red/dns1";
+       my $dns2file = "${General::swroot}/red/dns2";
+
+       # Write the obtained addresses to the ignore file.
+       print FILE "# IPFire local interfaces.\n";
+       print FILE "$green\n";
+
+       # Check if a blue interface exists.
+       if ($blue) {
+               # Add blue address.
+               print FILE "$blue\n";
+       }
+
+       # Check if an orange interface exists.
+       if ($orange) {
+               # Add orange address.
+               print FILE "$orange\n";
+       }
+
+       print FILE "\n# IPFire red interface, gateway and used DNS-servers.\n";
+       print FILE "# Include the corresponding files to obtain the addresses.\n";
+       print FILE "Include_File = $public_address_file\n";
+       print FILE "Include_File = $gatewayfile\n";
+       print FILE "Include_File = $dns1file\n";
+       print FILE "Include_File = $dns2file\n";
+
+       # Add all user defined hosts and networks to the ignore file.
+       #
+       # Check if the hash contains any elements.
+       if (keys (%ignored)) {
+               # Write headline.
+               print FILE "\n# User defined hosts/networks.\n";
+
+               # Loop through the entire hash and write the host/network
+               # and remark to the ignore file.
+               while ( (my $key) = each %ignored) {
+                       my $address = $ignored{$key}[0];
+                       my $remark = $ignored{$key}[1];
+                       my $status = $ignored{$key}[2];
+
+                       # Check if the status of the entry is "enabled".
+                       if ($status eq "enabled") {
+                               # Check if the address/network is valid.
+                               if ((&General::validip($address)) || (&General::validipandmask($address))) {
+                                       # Write the remark to the file.
+                                       print FILE "# $remark\n";
+
+                                       # Write the address/network to the ignore file.
+                                       print FILE "$address\n\n";
+                               }
+                       }
+                }
+       }
+
+       close(FILE);
+}
+
+# Private subfunction to obtain IP-addresses from given file names.
+#
+sub _get_address_from_file ($) {
+       my $file = shift;
+
+       # Check if the file exists.
+       if (-e $file) {
+               # Open the given file.
+               open(FILE, "$file") or die "Could not open $file.";
+
+               # Obtain the address from the first line of the file.
+               my $address = <FILE>;
+
+               # Close filehandle
+               close(FILE);
+
+               # Remove newlines.
+               chomp $address;
+
+               # Check if the grabbed address is valid.
+               if (&General::validip($address)) {
+                       # Return the address.
+                       return $address;
+               }
+       }
+
+       # Return nothing.
+       return;
+}