public inbox for development@lists.ipfire.org
 help / color / mirror / Atom feed
From: Michael Tremer <michael.tremer@ipfire.org>
To: development@lists.ipfire.org
Subject: Re: [PATCH] New addon: Portredirect 1.0
Date: Thu, 05 Aug 2021 22:33:32 +0200	[thread overview]
Message-ID: <147F4AEF-0264-4B59-AB39-D87B68883D17@ipfire.org> (raw)
In-Reply-To: <CD95E831-4AE9-40B7-BB91-27B3F3164270@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 74063 bytes --]

Hello,

> On 3 Aug 2021, at 18:04, Jon Murphy <jcmurphy26(a)gmail.com> wrote:
> 
> Hello all!
> 
> I’m having trouble following the changes to firewall.cgi.  I think there were 4 or 5 patches 
> submitted to the Dev Mailing List.
> 
> Did these get approved?

That is a good question. AFAIK they are not in c159.

> 
> I looked at the Changelog for Core 158 and core 159 (testing) but I didn’t see anything:
> 
> https://nightly.ipfire.org/core158/2021-07-21%2015:47:35%20+0000-23498c61/x86_64/changelog.txt
> 
> https://nightly.ipfire.org/master/latest/x86_64/changelog.txt
> 
> 
> Can they be added to CU 159?
> 
> To be honest I am mainly interested in the DNS redirect (and its cousin NTP redirect).
> 
> I’d be happy to help test but I do need some help applying the patches.  
> Right now I apply them by grabbing a copy of firewall.cgi and manually deleting and then manually adding a patch.
> Not the smartest way but it works (if I don’t screw-up and make a mistake!).

@Stefan: What is the status on this?

-Michael

> Jon
> 
>> On Jun 30, 2021, at 2:14 PM, Stefan Schantl <stefan.schantl(a)ipfire.org> wrote:
>> 
>> Hello Matthias, Hello Michael, Hello Jon, Hello *,
>> 
>> I've followed the conversation on this list since the first mail and
>> thoughts about forcing DNS traffic to use the local resolver.
>> 
>> It was a very long journey and lot of time and work has been spent to
>> get to the present point.
>> 
>> As Michael requested here, I've digged through the lines of the perl
>> script which is responsible for creating the firewall rules and
>> surprisingly found that everyting which is needed to create generic
>> REDIRECT rules already was written in the past - it just did not work
>> as designed/expected.
>> 
>> Finaly I was able to adjust these lines of code and to repair that
>> feature.
>> 
>> A redirect rule can be created by picking a single host or group of
>> hosts or entire network(s) as source, selecting NAT (DNAT) and choosing
>> the Firewall itself as target.
>> 
>> The protocol or service or service group which should be redirected has
>> to be selected afterwards. If you want to redirect a given port to
>> another one it can be specified as "Target port".
>> 
>> All created redirect rules are displayed as "input rules".
>> 
>> 
>> The patch directly can be accessed here:
>> 
>> https://patchwork.ipfire.org/project/ipfire/patch/20210630184031.7726-1-stefan.schantl(a)ipfire.org/
>> 
>> Best regards,
>> 
>> -Stefan
>> 
>>> Hello,
>>> 
>>>> On 28 Jun 2021, at 18:53, Jon Murphy <jcmurphy26(a)gmail.com> wrote:
>>>> 
>>>> Hi Michael!  Happy Monday!
>>>> 
>>>> 
>>>>> Why do we not extend the firewall UI probably by about 20 lines
>>>>> of code instead of adding many hundreds of lines?
>>>>> 
>>>>> Please can someone elaborate on this more?
>>>> 
>>>> Doing a DNS redirect, via the WegBUI, has been an issue since
>>>> 2015.  I found this quote in the old forum:
>>>> 
>>>> "Having investigated a bit more I have concluded that it's not
>>>> currently possible to create such rules through the WUI.
>>>> 
>>>> There are a number of obstacles:
>>>> 1. It is not allowed to create a rule where source IP and
>>>> destination nat IP is on the same subnetwork (e.g. GREEN), WUI
>>>> error message: "Source and destination IP addresses are from the
>>>> same subnet."
>>>> 
>>>> 2. WUI will not allow you to create a rule without a destination
>>>> (the filtered packet must adhere to a destination, not only a port)
>>>> and the destination MUST be an IP address of one of the IPFire
>>>> interfaces, which limits whats possible a great deal." 
>>> 
>>> And these cannot be changed?
>>> 
>>>> And I found this from 2016:
>>>> https://bugzilla.ipfire.org/show_bug.cgi?id=11168
>>>> 
>>>> So I am guessing that no one has been able to determine a way to
>>>> extend the WebGUI.  
>>> 
>>> Has anyone tried? I do not see any obvious reasons why this should
>>> not be possible.
>>> 
>>>> I am curious - Who created the 
>>>> https://ipfire:444/cgi-bin/firewall.cgi page?  And could they help?
>>> 
>>> -Michael
>>> 
>>>> Jon
>>>> 
>>>> 
>>>>> On Jun 28, 2021, at 11:04 AM, Michael Tremer <
>>>>> michael.tremer(a)ipfire.org> wrote:
>>>>> 
>>>>> Hello Matthias,
>>>>> 
>>>>>> On 27 Jun 2021, at 14:48, Matthias Fischer <
>>>>>> matthias.fischer(a)ipfire.org> wrote:
>>>>>> 
>>>>>> From: Marcel Lorenz <marcel.lorenz(a)ipfire.org>
>>>>> 
>>>>> Thank you for sending this patch on Marcel’s behalf, but I would
>>>>> much more prefer if he would submit his patches on his own. I do
>>>>> not see why that isn’t possible.
>>>>> 
>>>>>> Please note:
>>>>>> This is a new addon written by Marcel Lorenz <
>>>>>> marcel.lorenz(a)ipfire.org>.
>>>>>> 
>>>>>> It adds a new GUI to IPFire for DNS/NTP *and* user specific
>>>>>> port redirections.
>>>>>> 
>>>>>> How its working:
>>>>>> It has exactly the same functionalities as "Forcing
>>>>>> DNS/NTP..."  - and some more.
>>>>>> 
>>>>>> By setting switches, DNS/NTP requests are automatically
>>>>>> redirected to the local IPFire DNS/NTP servers.
>>>>>> 
>>>>>> Additionally, the user can specify custom redirections.
>>>>>> 
>>>>>> These rules are added to a new chain in PREROUTING =>
>>>>>> PORT_REDIRECT.
>>>>>> 
>>>>>> To avoid problems with (e.g.) transparent 'squid'
>>>>>> configurations,
>>>>>> redirection rules are added automatically before existing
>>>>>> 'squid' rules.
>>>>> 
>>>>> This message does unfortunately not say why this add-on would be
>>>>> useful. I am emphasising this again and again that it is not very
>>>>> important how something is done specially. That should be
>>>>> commented in the code and other implementation details should
>>>>> also be documented there.
>>>>> 
>>>>> As I have stated on this functionality many times before, I do
>>>>> not see why this is necessary at all.
>>>>> 
>>>>> Why is this an add-on?
>>>>> 
>>>>> Why do we not extend the firewall UI probably by about 20 lines
>>>>> of code instead of adding many hundreds of lines?
>>>>> 
>>>>> Please can someone elaborate on this more?
>>>>> 
>>>>> -Michael
>>>>> 
>>>>>> Signed-off-by: Matthias Fischer <matthias.fischer(a)ipfire.org>
>>>>>> ---
>>>>>> config/portredir/EX-portredir.menu    |   6 +
>>>>>> config/portredir/lang/portredir.de.pl |  19 +
>>>>>> config/portredir/lang/portredir.en.pl |  19 +
>>>>>> config/portredir/portredir-backup     |   1 +
>>>>>> config/portredir/portredir.cgi        | 525
>>>>>> ++++++++++++++++++++++++++
>>>>>> config/rootfiles/common/misc-progs    |   1 +
>>>>>> config/rootfiles/packages/portredir   |  11 +
>>>>>> lfs/portredir                         |  85 +++++
>>>>>> make.sh                               |   1 +
>>>>>> src/initscripts/packages/portredir    | 191 ++++++++++
>>>>>> src/misc-progs/Makefile               |   2 +-
>>>>>> src/misc-progs/portredirctrl.c        |  47 +++
>>>>>> src/paks/portredir/install.sh         |  32 ++
>>>>>> src/paks/portredir/uninstall.sh       |  28 ++
>>>>>> src/paks/portredir/update.sh          |  26 ++
>>>>>> 15 files changed, 993 insertions(+), 1 deletion(-)
>>>>>> create mode 100644 config/portredir/EX-portredir.menu
>>>>>> create mode 100644 config/portredir/lang/portredir.de.pl
>>>>>> create mode 100644 config/portredir/lang/portredir.en.pl
>>>>>> create mode 100644 config/portredir/portredir-backup
>>>>>> create mode 100644 config/portredir/portredir.cgi
>>>>>> create mode 100644 config/rootfiles/packages/portredir
>>>>>> create mode 100644 lfs/portredir
>>>>>> create mode 100644 src/initscripts/packages/portredir
>>>>>> create mode 100644 src/misc-progs/portredirctrl.c
>>>>>> create mode 100644 src/paks/portredir/install.sh
>>>>>> create mode 100644 src/paks/portredir/uninstall.sh
>>>>>> create mode 100644 src/paks/portredir/update.sh
>>>>>> 
>>>>>> diff --git a/config/portredir/EX-portredir.menu
>>>>>> b/config/portredir/EX-portredir.menu
>>>>>> new file mode 100644
>>>>>> index 000000000..8376e8053
>>>>>> --- /dev/null
>>>>>> +++ b/config/portredir/EX-portredir.menu
>>>>>> @@ -0,0 +1,6 @@
>>>>>> +    $subfirewall->{'95.portredir'} = {
>>>>>> +                               'caption' =>
>>>>>> $Lang::tr{'portredir port redirections'},
>>>>>> +                               'uri' => '/cgi-
>>>>>> bin/portredir.cgi',
>>>>>> +                               'title' =>
>>>>>> "$Lang::tr{'portredir port redirections'}",
>>>>>> +                               'enabled' => 1
>>>>>> +                               };
>>>>>> diff --git a/config/portredir/lang/portredir.de.pl
>>>>>> b/config/portredir/lang/portredir.de.pl
>>>>>> new file mode 100644
>>>>>> index 000000000..b932d4a85
>>>>>> --- /dev/null
>>>>>> +++ b/config/portredir/lang/portredir.de.pl
>>>>>> @@ -0,0 +1,19 @@
>>>>>> +%tr = (
>>>>>> +%tr,
>>>>>> +'portredir enable addon' => 'Addon aktivieren',
>>>>>> +'portredir common settings' => 'Allgemeine Einstellungen',
>>>>>> +'portredir port redirections' => 'Portumleitungen',
>>>>>> +'portredir fw for interface' => 'Firewalloptionen für das
>>>>>> Interface',
>>>>>> +'portredir enable user redirections' => 'Aktiviere
>>>>>> benutzerdefinierte Portumleitungen',
>>>>>> +'portredir force local dns' => 'Erzwinge lokale DNS-Server',
>>>>>> +'portredir force local ntp' => 'Erzwinge lokale NTP-Server',
>>>>>> +'portredir custom redirections' => 'Benutzerdefinierte
>>>>>> Portumleitungen',
>>>>>> +'portredir remove rule' => 'Entferne Regel',
>>>>>> +'portredir add rule' => 'Hinzufügen',
>>>>>> +'portredir no entries' => 'Keine Einträge vorhanden.',
>>>>>> +'portredir invalid address' => 'Ungültige Host-Addresse.',
>>>>>> +'portredir empty input' => 'Fehlende Angabe: Bitte geben Sie
>>>>>> einen gültigen Host an.',
>>>>>> +'portredir save to activate' => 'Speichern, um Änderungen zu
>>>>>> aktivieren',
>>>>>> +);
>>>>>> +
>>>>>> +#EOF
>>>>>> diff --git a/config/portredir/lang/portredir.en.pl
>>>>>> b/config/portredir/lang/portredir.en.pl
>>>>>> new file mode 100644
>>>>>> index 000000000..f442f3eaa
>>>>>> --- /dev/null
>>>>>> +++ b/config/portredir/lang/portredir.en.pl
>>>>>> @@ -0,0 +1,19 @@
>>>>>> +%tr = (
>>>>>> +%tr,
>>>>>> +'portredir enable addon' => 'Enable addon',
>>>>>> +'portredir common settings' => 'Common settings',
>>>>>> +'portredir port redirections' => 'Port redirections',
>>>>>> +'portredir fw for interface' => 'Firewall options for
>>>>>> interface',
>>>>>> +'portredir enable user redirections' => 'Enable user port
>>>>>> redirections',
>>>>>> +'portredir force local dns' => 'Enforce local DNS servers',
>>>>>> +'portredir force local ntp' => 'Enforce local NTP servers',
>>>>>> +'portredir custom redirections' => 'Custom port redirections',
>>>>>> +'portredir remove rule' => 'Remove rule',
>>>>>> +'portredir add rule' => 'Add new',
>>>>>> +'portredir no entries' => 'No entries at the moment.',
>>>>>> +'portredir invalid address' => 'Invalid host address.',
>>>>>> +'portredir empty input' => 'Empty input: Please enter a valid
>>>>>> host.',
>>>>>> +'portredir save to activate' => 'Save to activate changes',
>>>>>> +);
>>>>>> +
>>>>>> +#EOF
>>>>>> diff --git a/config/portredir/portredir-backup
>>>>>> b/config/portredir/portredir-backup
>>>>>> new file mode 100644
>>>>>> index 000000000..bd2ada742
>>>>>> --- /dev/null
>>>>>> +++ b/config/portredir/portredir-backup
>>>>>> @@ -0,0 +1 @@
>>>>>> +/var/ipfire/portredir
>>>>>> diff --git a/config/portredir/portredir.cgi
>>>>>> b/config/portredir/portredir.cgi
>>>>>> new file mode 100644
>>>>>> index 000000000..4913dda3f
>>>>>> --- /dev/null
>>>>>> +++ b/config/portredir/portredir.cgi
>>>>>> @@ -0,0 +1,525 @@
>>>>>> +#!/usr/bin/perl
>>>>>> +##############################################################
>>>>>> #################
>>>>>> +#                                                             
>>>>>>                 #
>>>>>> +# IPFire.org - A linux based
>>>>>> firewall                                         #
>>>>>> +# Copyright (C) 2021  IPFire Team 
>>>>>> <info(a)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        #
>>>>>> +# the Free Software Foundation, either version 3 of the
>>>>>> License, or           #
>>>>>> +# (at your option) any later
>>>>>> version.                                         #
>>>>>> +#                                                             
>>>>>>                 #
>>>>>> +# This program is distributed in the hope that it will be
>>>>>> useful,             #
>>>>>> +# but WITHOUT ANY WARRANTY; without even the implied warranty
>>>>>> of              #
>>>>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
>>>>>> the               #
>>>>>> +# GNU General Public License for more
>>>>>> details.                                #
>>>>>> +#                                                             
>>>>>>                 #
>>>>>> +# You should have received a copy of the GNU General Public
>>>>>> License           #
>>>>>> +# along with this program.  If not, see <
>>>>>> http://www.gnu.org/licenses/>.       #
>>>>>> +#                                                             
>>>>>>                 #
>>>>>> +##############################################################
>>>>>> #################
>>>>>> +
>>>>>> +use strict;
>>>>>> +
>>>>>> +# enable only the following on debugging purpose
>>>>>> +use warnings;
>>>>>> +use CGI::Carp 'fatalsToBrowser';
>>>>>> +
>>>>>> +require '/var/ipfire/general-functions.pl';
>>>>>> +require "${General::swroot}/lang.pl";
>>>>>> +require "${General::swroot}/header.pl";
>>>>>> +
>>>>>> +# File declarations
>>>>>> +my $settingsfile = "${General::swroot}/portredir/settings";
>>>>>> +my $redirectsfile = "${General::swroot}/portredir/redirects";
>>>>>> +
>>>>>> +# Create empty settingsfiles if they does not exist yet
>>>>>> +unless (-e "$settingsfile") { system ("touch $settingsfile");
>>>>>> }
>>>>>> +unless (-e "$redirectsfile") { system ("touch
>>>>>> $redirectsfile"); }
>>>>>> +
>>>>>> +# load ipfire settings
>>>>>> +our %netsettings = ();
>>>>>> +our %color = ();
>>>>>> +&General::readhash("${General::swroot}/ethernet/settings",
>>>>>> \%netsettings);
>>>>>> +&General::readhash("/srv/web/ipfire/html/themes/ipfire/include
>>>>>> /colors.txt", \%color);
>>>>>> +
>>>>>> +my %settings=();
>>>>>> +my %portredirs=();
>>>>>> +my %checked=(); # Checkbox manipulations
>>>>>> +my $errormessage='';
>>>>>> +my %selected=();
>>>>>> +our %redirects=();
>>>>>> +
>>>>>> +$settings{'ACTION'} = '';
>>>>>> +$settings{'REDIR_ENABLE_ADDON'}="off";
>>>>>> +$settings{'REDIR_CUSTOM_GREEN'}="off";
>>>>>> +$settings{'REDIR_CUSTOM_BLUE'}="off";
>>>>>> +$settings{'REDIR_CUSTOM_ORANGE'}="off";
>>>>>> +$settings{'REDIR_DNS_GREEN'}="off";
>>>>>> +$settings{'REDIR_NTP_GREEN'}="off";
>>>>>> +$settings{'REDIR_DNS_BLUE'}="off";
>>>>>> +$settings{'REDIR_NTP_BLUE'}="off";
>>>>>> +$settings{'REDIR_DNS_ORANGE'}="off";
>>>>>> +$settings{'REDIR_NTP_ORANGE'}="off";
>>>>>> +
>>>>>> +&Header::showhttpheaders();
>>>>>> +
>>>>>> +# Get GUI values
>>>>>> +&Header::getcgihash(\%settings);
>>>>>> +
>>>>>> +# Save action
>>>>>> +if ($settings{'ACTION'} eq $Lang::tr{'save'}) {
>>>>>> +
>>>>>> +       # If custom rules enabled, deactivate default rules on
>>>>>> interface
>>>>>> +       if ($settings{'REDIR_CUSTOM_GREEN'} eq "on" ) {
>>>>>> +               $settings{'REDIR_DNS_GREEN'}="off";
>>>>>> +               $settings{'REDIR_NTP_GREEN'}="off";
>>>>>> +       }
>>>>>> +
>>>>>> +       if ($settings{'REDIR_CUSTOM_BLUE'} eq "on" ) {
>>>>>> +               $settings{'REDIR_DNS_BLUE'}="off";
>>>>>> +               $settings{'REDIR_NTP_BLUE'}="off";
>>>>>> +       }
>>>>>> +
>>>>>> +       if ($settings{'REDIR_CUSTOM_ORANGE'} eq "on" ) {
>>>>>> +               $settings{'REDIR_DNS_ORANGE'}="off";
>>>>>> +               $settings{'REDIR_NTP_ORANGE'}="off";
>>>>>> +       }
>>>>>> +
>>>>>> +       &General::writehash($settingsfile, \%settings);
>>>>>> +
>>>>>> +       if ($settings{'REDIR_ENABLE_ADDON'} eq "on") {
>>>>>> +               system ('/usr/local/bin/portredirctrl restart
>>>>>>> /dev/null 2>&1');
>>>>>> +               system ('/usr/local/bin/portredirctrl enable
>>>>>>> /dev/null 2>&1');
>>>>>> +               &General::log('portredir addon: port
>>>>>> redirections enabled');
>>>>>> +       }
>>>>>> +       if ($settings{'REDIR_ENABLE_ADDON'} eq "off") {
>>>>>> +               system ('/usr/local/bin/portredirctrl disable
>>>>>>> /dev/null 2>&1');
>>>>>> +               system ('/usr/local/bin/portredirctrl stop
>>>>>>> /dev/null 2>&1');
>>>>>> +               &General::log('portredir addon: port
>>>>>> redirections disabled');
>>>>>> +       }
>>>>>> +
>>>>>> +# Add/edit an entry to the redirectsfile.
>>>>>> +
>>>>>> +} elsif (($settings{'ACTION'} eq $Lang::tr{'add'}) ||
>>>>>> ($settings{'ACTION'} eq $Lang::tr{'update'})) {
>>>>>> +
>>>>>> +       # Check if any input has been performed.
>>>>>> +       if ($settings{'REDIR_ENTRY_ADDRESS'} ne '') {
>>>>>> +
>>>>>> +               # Check if the given input is no valid IP-
>>>>>> address, display an error message.
>>>>>> +               if
>>>>>> (!&General::validip($settings{'REDIR_ENTRY_ADDRESS'}))  {
>>>>>> +                       $errormessage = "$Lang::tr{'portredir
>>>>>> invalid address'}";
>>>>>> +               }
>>>>>> +       } else {
>>>>>> +               $errormessage = "$Lang::tr{'portredir empty
>>>>>> input'}";
>>>>>> +       }
>>>>>> +
>>>>>> +       # Go further if there was no error.
>>>>>> +       if ($errormessage eq '') {
>>>>>> +               my %redirects = ();
>>>>>> +               my $id;
>>>>>> +               my $status;
>>>>>> +
>>>>>> +               # Assign hash values.
>>>>>> +               my $new_entry_interface =
>>>>>> $settings{'REDIR_ENTRY_INTERFACE'};
>>>>>> +               my $new_entry_protocol =
>>>>>> $settings{'REDIR_ENTRY_PROTOCOL'};
>>>>>> +               my $new_entry_port =
>>>>>> $settings{'REDIR_ENTRY_PORT'};
>>>>>> +               my $new_entry_address =
>>>>>> $settings{'REDIR_ENTRY_ADDRESS'};
>>>>>> +               my $new_entry_remark =
>>>>>> $settings{'REDIR_ENTRY_REMARK'};
>>>>>> +
>>>>>> +               # Read-in redirectsfile.
>>>>>> +               &General::readhasharray($redirectsfile,
>>>>>> \%redirects);
>>>>>> +
>>>>>> +               # 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 = $redirects{$id}[4];
>>>>>> +               } 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
>>>>>> %redirects;
>>>>>> +
>>>>>> +                       # 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 redirects
>>>>>> hash.
>>>>>> +               $redirects{$id} = ["$new_entry_interface",
>>>>>> "$new_entry_protocol", "$new_entry_port",
>>>>>> "$new_entry_address","$status", "$new_entry_remark"];
>>>>>> +
>>>>>> +               # Write the changed redirects hash to the
>>>>>> redirects file.
>>>>>> +               &General::writehasharray($redirectsfile,
>>>>>> \%redirects);
>>>>>> +       }
>>>>>> +
>>>>>> +# Toggle Enabled/Disabled for an existing entry on the
>>>>>> redirects list.
>>>>>> +
>>>>>> +} elsif ($settings{'ACTION'} eq $Lang::tr{'toggle enable
>>>>>> disable'}) {
>>>>>> +       my %redirects = ();
>>>>>> +
>>>>>> +       # 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'});
>>>>>> +
>>>>>> +               # Read-in ignoredfile.
>>>>>> +               &General::readhasharray($redirectsfile,
>>>>>> \%redirects);
>>>>>> +
>>>>>> +               # Grab the configured status of the
>>>>>> corresponding entry.
>>>>>> +               my $status = $redirects{$id}[4];
>>>>>> +
>>>>>> +               # Switch the status.
>>>>>> +               if ($status eq "disabled") {
>>>>>> +                       $status = "enabled";
>>>>>> +               } else {
>>>>>> +                       $status = "disabled";
>>>>>> +               }
>>>>>> +
>>>>>> +               # Modify the status of the existing entry.
>>>>>> +               $redirects{$id} = ["$redirects{$id}[0]",
>>>>>> "$redirects{$id}[1]", "$redirects{$id}[2]",
>>>>>> "$redirects{$id}[3]","$status", "$redirects{$id}[5]"];
>>>>>> +
>>>>>> +               # Write the changed ignored hash to the
>>>>>> redirects file.
>>>>>> +               &General::writehasharray($redirectsfile,
>>>>>> \%redirects);
>>>>>> +       }
>>>>>> +
>>>>>> +# Remove entry from redirects list.
>>>>>> +
>>>>>> +} elsif ($settings{'ACTION'} eq $Lang::tr{'remove'}) {
>>>>>> +       my %redirects = ();
>>>>>> +
>>>>>> +       # Read-in redirectsfile.
>>>>>> +       &General::readhasharray($redirectsfile, \%redirects);
>>>>>> +
>>>>>> +       # move data on key up
>>>>>> +       foreach my $key (sort keys %redirects) {
>>>>>> +               if ($key >= $settings{'ID'}) {
>>>>>> +                       my $next = $key + 1;
>>>>>> +                       if (exists $redirects{$next}) {
>>>>>> +                               foreach my $i (0 ..
>>>>>> $#{$redirects{$next}}) { $redirects{$key}[$i] =
>>>>>> $redirects{$next}[$i]; }
>>>>>> +                       }
>>>>>> +               }
>>>>>> +       }
>>>>>> +
>>>>>> +       my $last_key = (sort {$a <=> $b} keys %redirects)[-1];
>>>>>> +       delete $redirects{$last_key};
>>>>>> +
>>>>>> +       # Undef the given ID.
>>>>>> +       undef($settings{'ID'});
>>>>>> +
>>>>>> +       # Write the changed redirects hash to file.
>>>>>> +       &General::writehasharray($redirectsfile, \%redirects);
>>>>>> +}
>>>>>> +
>>>>>> +# Load settings from file
>>>>>> +&General::readhash($settingsfile, \%settings);
>>>>>> +&General::readhasharray($redirectsfile, \%redirects);
>>>>>> +
>>>>>> +# Call functions to generate whole page.
>>>>>> +&Header::openpage($Lang::tr{'portredir port redirections'}, 1,
>>>>>> '');
>>>>>> +&Header::openbigbox('100%', 'left', '', $errormessage);
>>>>>> +
>>>>>> +if ($errormessage) {
>>>>>> +        &Header::openbox('100%', 'left', $Lang::tr{'warning
>>>>>> messages'});
>>>>>> +        print "<font color='red'>$errormessage&nbsp;</font>";
>>>>>> +        &Header::closebox();
>>>>>> +}
>>>>>> +
>>>>>> +$checked{'REDIR_ENABLE_ADDON'}{'off'} = '';
>>>>>> +$checked{'REDIR_ENABLE_ADDON'}{'on'} = '';
>>>>>> +$checked{'REDIR_ENABLE_ADDON'}{$settings{'REDIR_ENABLE_ADDON'}
>>>>>> } = "checked='checked'";
>>>>>> +$checked{'REDIR_CUSTOM_GREEN'}{'off'} = '';
>>>>>> +$checked{'REDIR_CUSTOM_GREEN'}{'on'} = '';
>>>>>> +$checked{'REDIR_CUSTOM_GREEN'}{$settings{'REDIR_CUSTOM_GREEN'}
>>>>>> } = "checked='checked'";
>>>>>> +$checked{'REDIR_CUSTOM_BLUE'}{'off'} = '';
>>>>>> +$checked{'REDIR_CUSTOM_BLUE'}{'on'} = '';
>>>>>> +$checked{'REDIR_CUSTOM_BLUE'}{$settings{'REDIR_CUSTOM_BLUE'}}
>>>>>> = "checked='checked'";
>>>>>> +$checked{'REDIR_CUSTOM_ORANGE'}{'off'} = '';
>>>>>> +$checked{'REDIR_CUSTOM_ORANGE'}{'on'} = '';
>>>>>> +$checked{'REDIR_CUSTOM_ORANGE'}{$settings{'REDIR_CUSTOM_ORANGE
>>>>>> '}} = "checked='checked'";
>>>>>> +$checked{'REDIR_DNS_GREEN'}{'off'} = '';
>>>>>> +$checked{'REDIR_DNS_GREEN'}{'on'} = '';
>>>>>> +$checked{'REDIR_DNS_GREEN'}{$settings{'REDIR_DNS_GREEN'}} =
>>>>>> "checked='checked'";
>>>>>> +$checked{'REDIR_NTP_GREEN'}{'off'} = '';
>>>>>> +$checked{'REDIR_NTP_GREEN'}{'on'} = '';
>>>>>> +$checked{'REDIR_NTP_GREEN'}{$settings{'REDIR_NTP_GREEN'}} =
>>>>>> "checked='checked'";
>>>>>> +$checked{'REDIR_DNS_BLUE'}{'off'} = '';
>>>>>> +$checked{'REDIR_DNS_BLUE'}{'on'} = '';
>>>>>> +$checked{'REDIR_DNS_BLUE'}{$settings{'REDIR_DNS_BLUE'}} =
>>>>>> "checked='checked'";
>>>>>> +$checked{'REDIR_NTP_BLUE'}{'off'} = '';
>>>>>> +$checked{'REDIR_NTP_BLUE'}{'on'} = '';
>>>>>> +$checked{'REDIR_NTP_BLUE'}{$settings{'REDIR_NTP_BLUE'}} =
>>>>>> "checked='checked'";
>>>>>> +$checked{'REDIR_DNS_ORANGE'}{'off'} = '';
>>>>>> +$checked{'REDIR_DNS_ORANGE'}{'on'} = '';
>>>>>> +$checked{'REDIR_DNS_ORANGE'}{$settings{'REDIR_DNS_ORANGE'}} =
>>>>>> "checked='checked'";
>>>>>> +$checked{'REDIR_NTP_ORANGE'}{'off'} = '';
>>>>>> +$checked{'REDIR_NTP_ORANGE'}{'on'} = '';
>>>>>> +$checked{'REDIR_NTP_ORANGE'}{$settings{'REDIR_NTP_ORANGE'}} =
>>>>>> "checked='checked'";
>>>>>> +
>>>>>> +$selected{'REDIR_ENTRY_INTERFACE'}{$settings{'REDIR_ENTRY_INTE
>>>>>> RFACE'}} = 'selected';
>>>>>> +$selected{'REDIR_ENTRY_PROTOCOL'}{$settings{'REDIR_ENTRY_PROTO
>>>>>> COL'}} = 'selected';
>>>>>> +
>>>>>> +&showMainBox();
>>>>>> +&showRedirectsBox();
>>>>>> +
>>>>>> +&Header::closebigbox();
>>>>>> +&Header::closepage();
>>>>>> +
>>>>>> +# Function to show main settings and options.
>>>>>> +sub showMainBox() {
>>>>>> +
>>>>>> +       &Header::openbox('100%', 'center',
>>>>>> "$Lang::tr{'settings'}");
>>>>>> +       print "<form method='post'
>>>>>> action='$ENV{'SCRIPT_NAME'}'>";
>>>>>> +
>>>>>> +print <<END;
>>>>>> +<table width='80%' cellspacing='0' border='0'>
>>>>>> +       <tr><td colspan='2' class='base'
>>>>>> bgcolor='$color{'color20'}'><b>$Lang::tr{'portredir common
>>>>>> settings'}</b></td></tr
>>>>>> +       <tr>
>>>>>> +               <td width='25%'
>>>>>> class='base'>$Lang::tr{'portredir enable addon'}:</td>
>>>>>> +               <td><input type='checkbox'
>>>>>> name='REDIR_ENABLE_ADDON' $checked{'REDIR_ENABLE_ADDON'}{'on'}
>>>>>> /></td>
>>>>>> +       </tr>
>>>>>> +       <tr><td colspan='2'></td></tr>
>>>>>> +       <tr><td colspan='2'>&nbsp;</td></tr>
>>>>>> +END
>>>>>> +
>>>>>> +       # create html table with header line 1
>>>>>> +       print "<table width='80%' cellspacing='0'
>>>>>> border='0'><tr>";
>>>>>> +       print "<th class='base' width='40%'
>>>>>> align='left'><b>$Lang::tr{'portredir fw for interface'}</th>";
>>>>>> +       if ($netsettings{'GREEN_DEV'})  {print "<th
>>>>>> class='base' width='10%'><b><font
>>>>>> color=green>$Lang::tr{'green'}</font></th>";
>>>>>> +               } else {                 print "<th
>>>>>> class='base' width='10%'></font></th>"; }
>>>>>> +       if ($netsettings{'BLUE_DEV'})   {print "<th
>>>>>> class='base' width='10%'><b><font
>>>>>> color=blue>$Lang::tr{'blue'}</font></th>";
>>>>>> +               } else {                 print "<th
>>>>>> class='base' width='10%'></font></th>"; }
>>>>>> +       if ($netsettings{'ORANGE_DEV'}) {print "<th
>>>>>> class='base' width='10%'><b><font
>>>>>> color=orange>$Lang::tr{'orange'}</font></th>";
>>>>>> +               } else {                 print "<th
>>>>>> class='base' width='10%'></font></th>"; }
>>>>>> +
>>>>>> +       # the empty right row
>>>>>> +       print "<th class='base'
>>>>>> width='30%'><td></td></th></tr>";
>>>>>> +
>>>>>> +       # line 2
>>>>>> +       print "<tr><td>$Lang::tr{'portredir force local
>>>>>> dns'}</td>";
>>>>>> +       if ($netsettings{'GREEN_DEV'})  {print "<td
>>>>>> class='base' align='center'><input type='checkbox'
>>>>>> name='REDIR_DNS_GREEN'
>>>>>> $checked{'REDIR_DNS_GREEN'}{'on'}></td>";} else { print
>>>>>> "<td></td>";}
>>>>>> +       if ($netsettings{'BLUE_DEV'})   {print "<td
>>>>>> class='base' align='center'><input type='checkbox'
>>>>>> name='REDIR_DNS_BLUE' $checked{'REDIR_DNS_BLUE'}{'on'}></td>";}
>>>>>> else { print "<td></td>";}
>>>>>> +       if ($netsettings{'ORANGE_DEV'}) {print "<td
>>>>>> class='base' align='center'><input type='checkbox'
>>>>>> name='REDIR_DNS_ORANGE'
>>>>>> $checked{'REDIR_DNS_ORANGE'}{'on'}></td>";} else { print
>>>>>> "<td></td>";}
>>>>>> +
>>>>>> +       # line 3
>>>>>> +       print "</tr><tr><td>$Lang::tr{'portredir force local
>>>>>> ntp'}</td>";
>>>>>> +       if ($netsettings{'GREEN_DEV'})  {print "<td
>>>>>> class='base' align='center'><input type='checkbox'
>>>>>> name='REDIR_NTP_GREEN'
>>>>>> $checked{'REDIR_NTP_GREEN'}{'on'}></td>";} else { print
>>>>>> "<td></td>";}
>>>>>> +       if ($netsettings{'BLUE_DEV'})   {print "<td
>>>>>> class='base' align='center'><input type='checkbox'
>>>>>> name='REDIR_NTP_BLUE' $checked{'REDIR_NTP_BLUE'}{'on'}></td>";}
>>>>>> else { print "<td></td>";}
>>>>>> +       if ($netsettings{'ORANGE_DEV'}) {print "<td
>>>>>> class='base' align='center'><input type='checkbox'
>>>>>> name='REDIR_NTP_ORANGE'
>>>>>> $checked{'REDIR_NTP_ORANGE'}{'on'}></td>";} else { print
>>>>>> "<td></td>";}
>>>>>> +
>>>>>> +       # line 4
>>>>>> +       print "</tr><tr><td>$Lang::tr{'portredir enable user
>>>>>> redirections'}</td>";
>>>>>> +       if ($netsettings{'GREEN_DEV'})  {print "<td
>>>>>> class='base' align='center'><input type='checkbox'
>>>>>> name='REDIR_CUSTOM_GREEN'
>>>>>> $checked{'REDIR_CUSTOM_GREEN'}{'on'}></td>";} else { print
>>>>>> "<td></td>";}
>>>>>> +       if ($netsettings{'BLUE_DEV'})   {print "<td
>>>>>> class='base' align='center'><input type='checkbox'
>>>>>> name='REDIR_CUSTOM_BLUE'
>>>>>> $checked{'REDIR_CUSTOM_BLUE'}{'on'}></td>";} else { print
>>>>>> "<td></td>";}
>>>>>> +       if ($netsettings{'ORANGE_DEV'}) {print "<td
>>>>>> class='base' align='center'><input type='checkbox'
>>>>>> name='REDIR_CUSTOM_ORANGE'
>>>>>> $checked{'REDIR_CUSTOM_ORANGE'}{'on'}></td>";} else { print
>>>>>> "<td></td>";}
>>>>>> +
>>>>>> +       print <<END;
>>>>>> +       </tr></table>
>>>>>> +       <table width='80%' cellspacing='0' border='0'>
>>>>>> +               <tr><td colspan='2'>&nbsp;</td></tr>
>>>>>> +               <tr><td align='left'><b>$Lang::tr{'portredir
>>>>>> save to activate'}</b></td><td width='5%' align='center'><input
>>>>>> type='submit' name='ACTION' value='  $Lang::tr{'save'} 
>>>>>> '></td></tr>
>>>>>> +       </table></form>
>>>>>> +END
>>>>>> +
>>>>>> +&Header::closebox();
>>>>>> +}
>>>>>> +
>>>>>> +# Function to show elements of the redirects file and allow to
>>>>>> add or remove single members of it.
>>>>>> +sub showRedirectsBox() {
>>>>>> +        &Header::openbox('100%', 'center',
>>>>>> "$Lang::tr{'portredir custom redirections'}");
>>>>>> +
>>>>>> +       print <<END;
>>>>>> +               <table width='80%' cellspacing='1' border='0'>
>>>>>> +                       <tr>
>>>>>> +                               <td class='base'
>>>>>> bgcolor='$color{'color20'}'
>>>>>> align='center'><b>$Lang::tr{'interface'}</b></td>
>>>>>> +                               <td class='base'
>>>>>> bgcolor='$color{'color20'}'
>>>>>> align='center'><b>$Lang::tr{'protocol'}</b></td>
>>>>>> +                               <td class='base'
>>>>>> bgcolor='$color{'color20'}'
>>>>>> align='center'><b>$Lang::tr{'port'}</b></td>
>>>>>> +                               <td class='base'
>>>>>> bgcolor='$color{'color20'}' align='center'><b>$Lang::tr{'ip
>>>>>> address'}</b></td>
>>>>>> +                               <td class='base'
>>>>>> bgcolor='$color{'color20'}'
>>>>>> align='center'><b>$Lang::tr{'remark'}</b></td>
>>>>>> +                               <td class='base' colspan='3'
>>>>>> bgcolor='$color{'color20'}'></td>
>>>>>> +                       </tr>
>>>>>> +END
>>>>>> +                       # Check if some rules have been added
>>>>>> to be redirects.
>>>>>> +                       if (keys (%redirects)) {
>>>>>> +                               my $col = "";
>>>>>> +
>>>>>> +                               # List all entries of the hash.
>>>>>> +                               foreach my $key (sort keys
>>>>>> %redirects){
>>>>>> +
>>>>>> +                                       # Assign data array
>>>>>> positions to some nice variable names.
>>>>>> +                                       my $interface =
>>>>>> $redirects{$key}[0];
>>>>>> +                                       my $protocol =
>>>>>> $redirects{$key}[1];
>>>>>> +                                       my $port  =
>>>>>> $redirects{$key}[2];
>>>>>> +                                       my $address =
>>>>>> $redirects{$key}[3];
>>>>>> +                                       my $status  =
>>>>>> $redirects{$key}[4];
>>>>>> +                                       my $remark  =
>>>>>> $redirects{$key}[5];
>>>>>> +
>>>>>> +                                       # 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='15%'
>>>>>> class='base' align='center' $col><b><font
>>>>>> color=$interface>$Lang::tr{$interface}</font></b></td>
>>>>>> +                                               <td width='10%'
>>>>>> class='base' align='center' $col>$protocol</td>
>>>>>> +                                               <td width='10%'
>>>>>> class='base' align='center' $col>$port</td>
>>>>>> +                                               <td width='15%'
>>>>>> class='base' align='center' $col>&nbsp;$address</td>
>>>>>> +                                               <td width='40%'
>>>>>> class='base' align='center' $col>&nbsp;$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='$key'>
>>>>>> +                                                              
>>>>>>  <input type='hidden' name='ACTION'
>>>>>> value='$Lang::tr{'remove'}'>
>>>>>> +                                                       </form>
>>>>>> +                                               </td>
>>>>>> +                                       </tr>
>>>>>> +END
>>>>>> +                               }
>>>>>> +                       } else {
>>>>>> +                               # Print notice that currently
>>>>>> no ports are redirected.
>>>>>> +                               print "<tr>\n";
>>>>>> +                               print "<td class='base'
>>>>>> colspan='2'>$Lang::tr{'portredir no entries'}</td>\n";
>>>>>> +                               print "</tr>\n";
>>>>>> +                       }
>>>>>> +
>>>>>> +               print "</table>\n";
>>>>>> +
>>>>>> +       # Section to add new elements or edit existing ones.
>>>>>> +       print <<END;
>>>>>> +       <br>
>>>>>> +       <hr>
>>>>>> +       <br>
>>>>>> +       <div align='center'>
>>>>>> +               <table width='100%' cellspacing='0' border='0'>
>>>>>> +END
>>>>>> +
>>>>>> +       # Assign correct headline and button text.
>>>>>> +       my $buttontext;
>>>>>> +       my $entry_interface;
>>>>>> +       my $entry_protocol;
>>>>>> +       my $entry_port;
>>>>>> +       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='6'><b>$Lang::tr{'update'}</b></td></tr>\n";
>>>>>> +
>>>>>> +               # Grab address and remark for the given key.
>>>>>> +               $entry_interface =
>>>>>> $redirects{$settings{'ID'}}[0];
>>>>>> +               $entry_protocol =
>>>>>> $redirects{$settings{'ID'}}[1];
>>>>>> +               $entry_port = $redirects{$settings{'ID'}}[2];
>>>>>> +               $entry_address =
>>>>>> $redirects{$settings{'ID'}}[3];
>>>>>> +               $entry_remark = $redirects{$settings{'ID'}}[5];
>>>>>> +
>>>>>> +       } else {
>>>>>> +               $buttontext = $Lang::tr{'add'};
>>>>>> +               print "<tr><td class='boldbase'
>>>>>> colspan='11'><b>$Lang::tr{'dnsforward add a new
>>>>>> entry'}</b></td></tr>\n";
>>>>>> +               print "<tr><td>&nbsp</td></tr>\n";
>>>>>> +       }
>>>>>> +
>>>>>> +       print <<END;
>>>>>> +                       <tr>
>>>>>> +                               <td class='base' width='1%' 
>>>>>> bgcolor='$color{'color22'}'></td>
>>>>>> +                               <td class='base' width='15%'
>>>>>> bgcolor='$color{'color22'}'
>>>>>> align='left'><b>$Lang::tr{'interface'}</b></td>
>>>>>> +                               <td class='base' width='10%'
>>>>>> bgcolor='$color{'color22'}'
>>>>>> align='left'><b>$Lang::tr{'protocol'}</b></td>
>>>>>> +                               <td class='base' width='10%'
>>>>>> bgcolor='$color{'color22'}'
>>>>>> align='left'>&nbsp;<b>$Lang::tr{'port'}</b></td>
>>>>>> +                               <td class='base' width='13%'
>>>>>> bgcolor='$color{'color22'}' align='left'>&nbsp;<b>$Lang::tr{'ip
>>>>>> address'}</b></td>
>>>>>> +                               <td class='base' width='30%'
>>>>>> bgcolor='$color{'color22'}'
>>>>>> align='left'>&nbsp;<b>$Lang::tr{'remark'}</b></td>
>>>>>> +                               <td class='base' width='15%'
>>>>>> bgcolor='$color{'color22'}'></td>
>>>>>> +                               <td class='base' width='1%' 
>>>>>> bgcolor='$color{'color22'}'></td>
>>>>>> +                       </tr>
>>>>>> +
>>>>>> +                       <form method='post'
>>>>>> action='$ENV{'SCRIPT_NAME'}'>
>>>>>> +                       <input type='hidden' name='ID'
>>>>>> value='$settings{'ID'}'>
>>>>>> +                       <tr>
>>>>>> +                               <td class='base'></td>
>>>>>> +                               <td><select style='width:90px;'
>>>>>> id='interface' name='REDIR_ENTRY_INTERFACE'>
>>>>>> +END
>>>>>> +                               if ($netsettings{'GREEN_DEV'})
>>>>>> {
>>>>>> +                                       if ($entry_interface eq
>>>>>> "green") {
>>>>>> +                                               print "<option
>>>>>> value='green' selected='selected'
>>>>>> {'green'}>$Lang::tr{'green'}</option>";
>>>>>> +                                       } else { print "<option
>>>>>> value='green' {'green'}>$Lang::tr{'green'}</option>";}
>>>>>> +                               }
>>>>>> +                               if ($netsettings{'BLUE_DEV'}) {
>>>>>> +                                       if ($entry_interface eq
>>>>>> "blue") { 
>>>>>> +                                               print "<option
>>>>>> value='blue' selected='selected'
>>>>>> {'blue'}>$Lang::tr{'blue'}</option>";
>>>>>> +                                       } else { print "<option
>>>>>> value='blue' {'blue'}>$Lang::tr{'blue'}</option>";}
>>>>>> +                               }
>>>>>> +                               if ($netsettings{'ORANGE_DEV'})
>>>>>> {
>>>>>> +                                       if ($entry_interface eq
>>>>>> "orange") { 
>>>>>> +                                               print "<option
>>>>>> value='orange' selected='selected'
>>>>>> {'orange'}>$Lang::tr{'orange'}</option>";
>>>>>> +                                       } else { print "<option
>>>>>> value='orange' {'orange'}>$Lang::tr{'orange'}</option>";}
>>>>>> +                               }
>>>>>> +
>>>>>> +                       print "</select><td><select
>>>>>> style='width:50px;' name='REDIR_ENTRY_PROTOCOL'>";
>>>>>> +                       if ((!$entry_protocol) ||
>>>>>> ($entry_protocol eq "tcp")) {
>>>>>> +                               print "<option
>>>>>> selected='selected' id='protocol' value='tcp'
>>>>>> {'tcp'}>tcp</option>";
>>>>>> +                               print "<option value='udp'
>>>>>> {'udp'}>udp</option>";
>>>>>> +                       } elsif ($entry_protocol eq "udp") {
>>>>>> +                               print "<option value='tcp'
>>>>>> {'tcp'}>tcp</option>";
>>>>>> +                               print "<option
>>>>>> selected='selected' value='udp' {'udp'}>udp</option>";
>>>>>> +                       }
>>>>>> +       print <<END;
>>>>>> +                               </select></td>
>>>>>> +                               <td><input type='text'
>>>>>> name='REDIR_ENTRY_PORT'    value='$entry_port'   
>>>>>> size='4'></td>
>>>>>> +                               <td><input type='text'
>>>>>> name='REDIR_ENTRY_ADDRESS' value='$entry_address'
>>>>>> size='14'></td>
>>>>>> +                               <td><input type='text'
>>>>>> name='REDIR_ENTRY_REMARK'  value='$entry_remark' 
>>>>>> size='35'></td>
>>>>>> +                               <td width='10%'
>>>>>> align='center'><input type='submit' name='ACTION' value=' 
>>>>>> $buttontext  '></td>
>>>>>> +                               <td class='base'></td>
>>>>>> +                       </tr>
>>>>>> +                       </form>
>>>>>> +               </table>
>>>>>> +       </div>
>>>>>> +END
>>>>>> +       &Header::closebox();
>>>>>> +}
>>>>>> diff --git a/config/rootfiles/common/misc-progs
>>>>>> b/config/rootfiles/common/misc-progs
>>>>>> index d6594b3f8..fbad2af8b 100644
>>>>>> --- a/config/rootfiles/common/misc-progs
>>>>>> +++ b/config/rootfiles/common/misc-progs
>>>>>> @@ -17,6 +17,7 @@ usr/local/bin/logwatch
>>>>>> #usr/local/bin/mpfirectrl
>>>>>> usr/local/bin/openvpnctrl
>>>>>> usr/local/bin/pakfire
>>>>>> +#usr/local/bin/portredirctrl
>>>>>> usr/local/bin/qosctrl
>>>>>> usr/local/bin/rebuildhosts
>>>>>> usr/local/bin/rebuildroutes
>>>>>> diff --git a/config/rootfiles/packages/portredir
>>>>>> b/config/rootfiles/packages/portredir
>>>>>> new file mode 100644
>>>>>> index 000000000..4b4ba8366
>>>>>> --- /dev/null
>>>>>> +++ b/config/rootfiles/packages/portredir
>>>>>> @@ -0,0 +1,11 @@
>>>>>> +etc/rc.d/init.d/portredir
>>>>>> +etc/rc.d/rc0.d/K77portredir
>>>>>> +etc/rc.d/rc3.d/S23portredir
>>>>>> +etc/rc.d/rc6.d/K77portredir
>>>>>> +srv/web/ipfire/cgi-bin/portredir.cgi
>>>>>> +usr/local/bin/portredirctrl
>>>>>> +var/ipfire/addon-lang/portredir.de.pl
>>>>>> +var/ipfire/addon-lang/portredir.en.pl
>>>>>> +var/ipfire/backup/addons/includes/portredir
>>>>>> +var/ipfire/menu.d/EX-portredir.menu
>>>>>> +var/ipfire/portredir
>>>>>> diff --git a/lfs/portredir b/lfs/portredir
>>>>>> new file mode 100644
>>>>>> index 000000000..a4911f71f
>>>>>> --- /dev/null
>>>>>> +++ b/lfs/portredir
>>>>>> @@ -0,0 +1,85 @@
>>>>>> +##############################################################
>>>>>> #################
>>>>>> +#                                                             
>>>>>>                 #
>>>>>> +# IPFire.org - A linux based
>>>>>> firewall                                         #
>>>>>> +# Copyright (C) 2007-2021  IPFire Team 
>>>>>> <info(a)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        #
>>>>>> +# the Free Software Foundation, either version 3 of the
>>>>>> License, or           #
>>>>>> +# (at your option) any later
>>>>>> version.                                         #
>>>>>> +#                                                             
>>>>>>                 #
>>>>>> +# This program is distributed in the hope that it will be
>>>>>> useful,             #
>>>>>> +# but WITHOUT ANY WARRANTY; without even the implied warranty
>>>>>> of              #
>>>>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
>>>>>> the               #
>>>>>> +# GNU General Public License for more
>>>>>> details.                                #
>>>>>> +#                                                             
>>>>>>                 #
>>>>>> +# You should have received a copy of the GNU General Public
>>>>>> License           #
>>>>>> +# along with this program.  If not, see <
>>>>>> http://www.gnu.org/licenses/>.       #
>>>>>> +#                                                             
>>>>>>                 #
>>>>>> +##############################################################
>>>>>> #################
>>>>>> +
>>>>>> +##############################################################
>>>>>> #################
>>>>>> +# Definitions
>>>>>> +##############################################################
>>>>>> #################
>>>>>> +
>>>>>> +include Config
>>>>>> +
>>>>>> +VER        = 1.0
>>>>>> +
>>>>>> +THISAPP    = portredir-$(VER)
>>>>>> +DIR_APP    = $(DIR_SRC)/$(THISAPP)
>>>>>> +TARGET     = $(DIR_INFO)/$(THISAPP)
>>>>>> +PROG       = portredir
>>>>>> +PAK_VER    = 1
>>>>>> +
>>>>>> +##############################################################
>>>>>> #################
>>>>>> +# Top-level Rules
>>>>>> +##############################################################
>>>>>> #################
>>>>>> +
>>>>>> +install : $(TARGET)
>>>>>> +
>>>>>> +check :
>>>>>> +
>>>>>> +download :
>>>>>> +
>>>>>> +md5 :
>>>>>> +
>>>>>> +dist: 
>>>>>> +       @$(PAK)
>>>>>> +
>>>>>> +##############################################################
>>>>>> #################
>>>>>> +# Installation Details
>>>>>> +##############################################################
>>>>>> #################
>>>>>> +
>>>>>> +$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
>>>>>> +       @$(PREBUILD)
>>>>>> +       @rm -rf $(DIR_APP) && cd $(DIR_SRC)
>>>>>> +
>>>>>> +       #install cgi 
>>>>>> +       install -v -m 755 $(DIR_CONF)/portredir/portredir.cgi
>>>>>> /srv/web/ipfire/cgi-bin/
>>>>>> +
>>>>>> +       #create configuration dir 
>>>>>> +       -mkdir -pv /var/ipfire/portredir/
>>>>>> +       chown -R nobody:nobody /var/ipfire/portredir/
>>>>>> +
>>>>>> +       # Install include file for backup
>>>>>> +       install -v -m 644 $(DIR_CONF)/portredir/portredir-
>>>>>> backup /var/ipfire/backup/addons/includes/portredir
>>>>>> +
>>>>>> +       # Install menu file
>>>>>> +       install -v -m 644 $(DIR_CONF)/portredir/EX-
>>>>>> portredir.menu /var/ipfire/menu.d/
>>>>>> +       chown nobody:nobody /var/ipfire/menu.d/EX-
>>>>>> portredir.menu
>>>>>> +
>>>>>> +       # Install addon-specific language-files
>>>>>> +       install -v -m 644
>>>>>> $(DIR_CONF)/portredir/lang/portredir.*.pl /var/ipfire/addon-
>>>>>> lang/
>>>>>> +
>>>>>> +       #install initscripts
>>>>>> +       $(call INSTALL_INITSCRIPT,portredir)
>>>>>> +
>>>>>> +       # Create symlinks for runlevel interaction.
>>>>>> +       ln -svf /etc/rc.d/init.d/portredir
>>>>>> /etc/rc.d/rc3.d/S23portredir
>>>>>> +       ln -svf /etc/rc.d/init.d/portredir
>>>>>> /etc/rc.d/rc0.d/K77portredir
>>>>>> +       ln -svf /etc/rc.d/init.d/portredir
>>>>>> /etc/rc.d/rc6.d/K77portredir
>>>>>> +
>>>>>> +       @rm -rf $(DIR_APP)
>>>>>> +       @$(POSTBUILD)
>>>>>> +
>>>>>> diff --git a/make.sh b/make.sh
>>>>>> index fc03ebcd5..ab9fe881a 100755
>>>>>> --- a/make.sh
>>>>>> +++ b/make.sh
>>>>>> @@ -1623,6 +1623,7 @@ buildipfire() {
>>>>>>  lfsmake2 socat
>>>>>>  lfsmake2 libcdada
>>>>>>  lfsmake2 pmacct
>>>>>> +  lfsmake2 portredir
>>>>>> }
>>>>>> 
>>>>>> buildinstaller() {
>>>>>> diff --git a/src/initscripts/packages/portredir
>>>>>> b/src/initscripts/packages/portredir
>>>>>> new file mode 100644
>>>>>> index 000000000..cc57fb9cc
>>>>>> --- /dev/null
>>>>>> +++ b/src/initscripts/packages/portredir
>>>>>> @@ -0,0 +1,191 @@
>>>>>> +#!/bin/sh
>>>>>> +##############################################################
>>>>>> ##########
>>>>>> +# Begin $rc_base/init.d/portredir
>>>>>> +#
>>>>>> +# Description : portredir init script for DNS/NTP and custom 
>>>>>> +#              port redirection rules
>>>>>> +#
>>>>>> +##############################################################
>>>>>> ##########
>>>>>> +
>>>>>> +. /etc/sysconfig/rc
>>>>>> +. ${rc_functions}
>>>>>> +
>>>>>> +IPT="/sbin/iptables";
>>>>>> +parent_chain="PREROUTING";
>>>>>> +chain="PORT_REDIRECT";
>>>>>> +
>>>>>> +confdir="/var/ipfire/portredir";
>>>>>> +settingsfile="${confdir}/settings";
>>>>>> +redirectsfile="${confdir}/redirects";
>>>>>> +SYSLOG="NO";
>>>>>> +VERBOSE="NO";
>>>>>> +
>>>>>> +eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings);
>>>>>> +eval $(/usr/local/bin/readhash ${settingsfile});
>>>>>> +
>>>>>> +logtext() {
>>>>>> +       if [ "${SYSLOG}" = "YES" ]; then logger -t "portredir"
>>>>>> ${1}; fi;
>>>>>> +       if [ "${VERBOSE}" = "YES" ]; then echo ${1}; fi;}
>>>>>> +
>>>>>> +create_chain() {
>>>>>> +
>>>>>> +       local line=$(${IPT} -t nat -L ${parent_chain} --line-
>>>>>> numbers |grep "SQUID" |awk '{printf($1)}');
>>>>>> +
>>>>>> +       if [[ "${REDIR_ENABLE_ADDON}" == "off" || -z
>>>>>> "${REDIR_ENABLE_ADDON}" ]]; then
>>>>>> +               logtext "addon not enabled in web
>>>>>> interface...";
>>>>>> +               echo "Portredir addon not enabled in web
>>>>>> interface...";
>>>>>> +               exit 0;
>>>>>> +       fi;
>>>>>> +
>>>>>> +       if [ -z "$(${IPT} -t nat -L ${parent_chain} |grep
>>>>>> ${chain})" ]; then
>>>>>> +               ${IPT} -t nat -N ${chain};
>>>>>> +
>>>>>> +               if [ ! -z "${line}" ]; then
>>>>>> +                       logtext "create chain ${chain} and link
>>>>>> in ${parent_chain} at position ${line}...";
>>>>>> +                       ${IPT} -t nat -I ${parent_chain}
>>>>>> ${line} -j ${chain};
>>>>>> +               else
>>>>>> +                       logtext "create chain ${chain} and link
>>>>>> in ${parent_chain} at last position...";
>>>>>> +                       ${IPT} -t nat -A ${parent_chain} -j
>>>>>> ${chain};
>>>>>> +               fi
>>>>>> +       else
>>>>>> +               return 1;
>>>>>> +       fi;
>>>>>> +       return 0;
>>>>>> +}
>>>>>> +
>>>>>> +remove_chain() {
>>>>>> +       if [ ! -z "$(${IPT} -t nat -L ${parent_chain} |grep
>>>>>> ${chain})" ]; then
>>>>>> +               logtext "remove chain ${chain} and link in
>>>>>> ${parent_chain} from system...";
>>>>>> +               ${IPT} -t nat -D "${parent_chain}" -j ${chain};
>>>>>> +               ${IPT} -t nat -F ${chain};
>>>>>> +               ${IPT} -t nat -X ${chain};
>>>>>> +       else
>>>>>> +               return 1;
>>>>>> +       fi;
>>>>>> +       return 0;
>>>>>> +}
>>>>>> +
>>>>>> +activate_custom_redirections() {
>>>>>> +       
>>>>>> +       local array=();
>>>>>> +       local redirects=();
>>>>>> +       local i;
>>>>>> +       index=();
>>>>>> +       iface=();
>>>>>> +       protocol=();
>>>>>> +       port=();
>>>>>> +       targetip=();
>>>>>> +       enabled=();
>>>>>> +
>>>>>> +       IFS=$'\n' read -d '' -ra redirects < ${redirectsfile};
>>>>>> +
>>>>>> +       for i in "${!redirects[@]}"
>>>>>> +       do
>>>>>> +               IFS=$',' read -ra array <<< ${redirects[i]};
>>>>>> +               index[i]=${array[0]};
>>>>>> +               iface[i]=${array[1]};
>>>>>> +               protocol[i]=${array[2]};
>>>>>> +               port[i]=${array[3]};
>>>>>> +               targetip[i]=${array[4]};
>>>>>> +               enabled[i]=${array[5]};
>>>>>> +       done
>>>>>> +
>>>>>> +       for i in "${!index[@]}"
>>>>>> +       do
>>>>>> +               if [[ ! -z "${GREEN_DEV}" &&  "${iface[i]}" =
>>>>>> "green" && "${enabled[i]}" = "enabled" ]]; then
>>>>>> +
>>>>>> +                       logtext "add redirect in ${chain} on
>>>>>> ${GREEN_DEV} ip ${targetip[i]} protocol ${protocol[i]} port
>>>>>> ${port[i]} ";
>>>>>> +                       ${IPT} -t nat -A ${chain} -i
>>>>>> ${GREEN_DEV} -d ${targetip[i]} -p ${protocol[i]} -m
>>>>>> ${protocol[i]} --dport ${port[i]} -j RETURN;
>>>>>> +                       ${IPT} -t nat -A ${chain} -i
>>>>>> ${GREEN_DEV} -p ${protocol[i]} -m ${protocol[i]} --dport
>>>>>> ${port[i]} -j REDIRECT;
>>>>>> +               fi
>>>>>> +               if [[ ! -z "${BLUE_DEV}" &&  "${iface[i]}" =
>>>>>> "blue" && "${enabled[i]}" = "enabled" ]]; then
>>>>>> +                       logtext "add redirect in ${chain} on
>>>>>> ${BLUE_DEV} ip ${targetip[i]} protocol ${protocol[i]} port
>>>>>> ${port[i]} ";
>>>>>> +                       ${IPT} -t nat -A ${chain} -i
>>>>>> ${BLUE_DEV} -d ${targetip[i]} -p ${protocol[i]} -m
>>>>>> ${protocol[i]} --dport ${port[i]} -j RETURN;
>>>>>> +                       ${IPT} -t nat -A ${chain} -i
>>>>>> ${BLUE_DEV} -p ${protocol[i]} -m ${protocol[i]} --dport
>>>>>> ${port[i]} -j REDIRECT;
>>>>>> +               fi
>>>>>> +               if [[ ! -z "${ORANGE_DEV}" &&  "${iface[i]}" =
>>>>>> "orange" && "${enabled[i]}" = "enabled" ]]; then
>>>>>> +                       logtext "add redirect in ${chain} on
>>>>>> ${ORANGE_DEV} ip ${targetip[i]} protocol ${protocol[i]} port
>>>>>> ${port[i]} ";
>>>>>> +                       ${IPT} -t nat -A ${chain} -i
>>>>>> ${ORANGE_DEV} -d ${targetip[i]} -p ${protocol[i]} -m
>>>>>> ${protocol[i]} --dport ${port[i]} -j RETURN;
>>>>>> +                       ${IPT} -t nat -A ${chain} -i
>>>>>> ${ORANGE_DEV} -p ${protocol[i]} -m ${protocol[i]} --dport
>>>>>> ${port[i]} -j REDIRECT;
>>>>>> +               fi
>>>>>> +       done
>>>>>> +       unset array redirects i index iface protocol port
>>>>>> targetip enabled;
>>>>>> +       return 0;
>>>>>> +}
>>>>>> +
>>>>>> +activate_redirections() {
>>>>>> +
>>>>>> +       if ! create_chain; then return 1; fi;
>>>>>> +       
>>>>>> +       # Force DNS REDIRECTs on GREEN (udp, tcp, 53)
>>>>>> +       if [[ "${REDIR_DNS_GREEN}" == "on" && 
>>>>>> "${REDIR_CUSTOM_GREEN}" = "off" ]]; then
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${GREEN_DEV} -d
>>>>>> ${GREEN_ADDRESS} -p udp -m udp --dport domain -j RETURN;
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${GREEN_DEV} -p
>>>>>> udp -m udp --dport domain -j REDIRECT;
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${GREEN_DEV} -d
>>>>>> ${GREEN_ADDRESS} -p tcp -m tcp --dport domain -j RETURN;
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${GREEN_DEV} -p
>>>>>> tcp -m tcp --dport domain -j REDIRECT;
>>>>>> +       fi
>>>>>> +
>>>>>> +       # Force DNS REDIRECTs on BLUE (udp, tcp, 53)
>>>>>> +       if [[ "${REDIR_DNS_BLUE}" == "on" && 
>>>>>> "${REDIR_CUSTOM_BLUE}" = "off" ]]; then
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${BLUE_DEV} -d
>>>>>> ${BLUE_ADDRESS} -p udp -m udp --dport domain -j RETURN
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${BLUE_DEV} -p udp
>>>>>> -m udp --dport domain -j REDIRECT
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${BLUE_DEV} -d
>>>>>> ${BLUE_ADDRESS} -p tcp -m tcp --dport domain -j RETURN
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${BLUE_DEV} -p tcp
>>>>>> -m tcp --dport domain -j REDIRECT
>>>>>> +       fi
>>>>>> +
>>>>>> +       # Force DNS REDIRECTs on ORANGE (udp, tcp, 53)
>>>>>> +       if [[ "${REDIR_DNS_ORANGE}" == "on" && 
>>>>>> "${REDIR_CUSTOM_ORANGE}" = "off" ]]; then
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${ORANGE_DEV} -d
>>>>>> ${ORANGE_ADDRESS} -p udp -m udp --dport domain -j RETURN
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${ORANGE_DEV} -p
>>>>>> udp -m udp --dport domain -j REDIRECT
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${ORANGE_DEV} -d
>>>>>> ${ORANGE_ADDRESS} -p tcp -m tcp --dport domain -j RETURN
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${ORANGE_DEV} -p
>>>>>> tcp -m tcp --dport domain -j REDIRECT
>>>>>> +       fi
>>>>>> +
>>>>>> +       # Force NTP REDIRECTs on GREEN (udp, 123)
>>>>>> +       if [[ "${REDIR_NTP_GREEN}" == "on" && 
>>>>>> "${REDIR_CUSTOM_GREEN}" = "off" ]]; then
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${GREEN_DEV} -d
>>>>>> ${GREEN_ADDRESS} -p udp -m udp --dport ntp -j RETURN
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${GREEN_DEV} -p
>>>>>> udp -m udp --dport ntp -j REDIRECT
>>>>>> +       fi
>>>>>> +
>>>>>> +       # Force NTP REDIRECTs on BLUE (udp, 123)
>>>>>> +       if [[ "${REDIR_NTP_BLUE}" == "on" && 
>>>>>> "${REDIR_CUSTOM_BLUE}" = "off" ]]; then
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${BLUE_DEV} -d
>>>>>> ${BLUE_ADDRESS} -p udp -m udp --dport ntp -j RETURN
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${BLUE_DEV} -p udp
>>>>>> -m udp --dport ntp -j REDIRECT
>>>>>> +       fi
>>>>>> +
>>>>>> +       # Force NTP REDIRECTs on ORANGE (udp, 123)
>>>>>> +       if [[ "${REDIR_NTP_ORANGE}" == "on" && 
>>>>>> "${REDIR_CUSTOM_ORANGE}" = "off" ]]; then
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${ORANGE_DEV} -d
>>>>>> ${ORANGE_ADDRESS} -p udp -m udp --dport ntp -j RETURN
>>>>>> +               ${IPT} -t nat -A ${chain} -i ${ORANGE_DEV} -p
>>>>>> udp -m udp --dport ntp -j REDIRECT
>>>>>> +       fi
>>>>>> +
>>>>>> +       if ! activate_custom_redirections; then return 1; fi;
>>>>>> +
>>>>>> +       return 0;
>>>>>> +}
>>>>>> +
>>>>>> +case "${1}" in
>>>>>> +       start)
>>>>>> +               boot_mesg "Loading port redirections..."
>>>>>> +               activate_redirections;
>>>>>> +               evaluate_retval;
>>>>>> +               ;;
>>>>>> +
>>>>>> +       stop)   
>>>>>> +               boot_mesg "Removing port redirections..."
>>>>>> +               remove_chain;
>>>>>> +               evaluate_retval;
>>>>>> +               ;;
>>>>>> +
>>>>>> +       restart)
>>>>>> +               ${0} stop
>>>>>> +               ${0} start
>>>>>> +               ;;
>>>>>> +
>>>>>> +       *)
>>>>>> +               echo "Usage: ${0} {start|stop|restart}"
>>>>>> +               exit 1
>>>>>> +               ;;
>>>>>> +esac
>>>>>> +
>>>>>> +# End $rc_base/init.d/portredir
>>>>>> diff --git a/src/misc-progs/Makefile b/src/misc-progs/Makefile
>>>>>> index 7c3ef7529..850f8fdcc 100644
>>>>>> --- a/src/misc-progs/Makefile
>>>>>> +++ b/src/misc-progs/Makefile
>>>>>> @@ -30,7 +30,7 @@ SUID_PROGS = squidctrl sshctrl ipfirereboot \
>>>>>>         wirelessctrl getipstat qosctrl \
>>>>>>         redctrl syslogdctrl extrahdctrl sambactrl \
>>>>>>         smartctrl clamavctrl addonctrl pakfire mpfirectrl
>>>>>> wlanapctrl \
>>>>>> -       setaliases urlfilterctrl updxlratorctrl fireinfoctrl
>>>>>> rebuildroutes \
>>>>>> +       setaliases urlfilterctrl updxlratorctrl fireinfoctrl
>>>>>> rebuildroutes portredirctrl \
>>>>>>         getconntracktable wirelessclient torctrl ddnsctrl
>>>>>> unboundctrl \
>>>>>>         captivectrl
>>>>>> 
>>>>>> diff --git a/src/misc-progs/portredirctrl.c b/src/misc-
>>>>>> progs/portredirctrl.c
>>>>>> new file mode 100644
>>>>>> index 000000000..7897d711c
>>>>>> --- /dev/null
>>>>>> +++ b/src/misc-progs/portredirctrl.c
>>>>>> @@ -0,0 +1,47 @@
>>>>>> +/* This file is part of the IPFire Firewall.
>>>>>> + *
>>>>>> + * This program is distributed under the terms of the GNU
>>>>>> General Public
>>>>>> + * Licence.  See the file COPYING for details.
>>>>>> + *
>>>>>> + */
>>>>>> +
>>>>>> +#include <stdlib.h>
>>>>>> +#include <stdio.h>
>>>>>> +#include <string.h>
>>>>>> +#include <unistd.h>
>>>>>> +#include <sys/types.h>
>>>>>> +#include <fcntl.h>
>>>>>> +#include "setuid.h"
>>>>>> +
>>>>>> +int main(int argc, char *argv[]) {
>>>>>> +       if (!(initsetuid()))
>>>>>> +               exit(1);
>>>>>> +
>>>>>> +       // Check what command is asked
>>>>>> +        if (argc < 2) {
>>>>>> +                fprintf(stderr, "\nNo argument
>>>>>> given.\n\nportredirctrl
>>>>>> (start|stop|restart|enable|disable)\n\n");
>>>>>> +                exit(1);
>>>>>> +        }
>>>>>> +
>>>>>> +        if (strcmp(argv[1], "start") == 0) {
>>>>>> +                safe_system("/etc/rc.d/init.d/portredir
>>>>>> start");
>>>>>> +        } else if (strcmp(argv[1], "stop") == 0) {
>>>>>> +                safe_system("/etc/rc.d/init.d/portredir
>>>>>> stop");
>>>>>> +        } else if (strcmp(argv[1], "restart") == 0) {
>>>>>> +                safe_system("/etc/rc.d/init.d/portredir
>>>>>> restart");
>>>>>> +       } else if (strcmp(argv[1], "enable") == 0) {
>>>>>> +               safe_system("touch
>>>>>> /var/ipfire/portredir/enable");
>>>>>> +               safe_system("ln -snf /etc/rc.d/init.d/portredir
>>>>>> /etc/rc.d/rc3.d/S23portredir >/dev/null 2>&1");
>>>>>> +               safe_system("ln -snf /etc/rc.d/init.d/portredir
>>>>>> /etc/rc.d/rc0.d/K77portredir >/dev/null 2>&1");
>>>>>> +               safe_system("ln -snf /etc/rc.d/init.d/portredir
>>>>>> /etc/rc.d/rc6.d/K77portredir >/dev/null 2>&1");
>>>>>> +       } else if (strcmp(argv[1], "disable") == 0) {
>>>>>> +               safe_system("/etc/rc.d/init.d/portredir stop");
>>>>>> +               safe_system("unlink
>>>>>> /var/ipfire/portredir/enable");
>>>>>> +               safe_system("rm -rf /etc/rc.d/rc*.d/*portredir
>>>>>>> /dev/null 2>&1");
>>>>>> +        } else {
>>>>>> +                fprintf(stderr, "\nBad argument
>>>>>> given.\n\nportredirctrl
>>>>>> (start|stop|restart|enable|disable)\n\n");
>>>>>> +                exit(1);
>>>>>> +        }
>>>>>> +
>>>>>> +       return 0;
>>>>>> +}
>>>>>> diff --git a/src/paks/portredir/install.sh
>>>>>> b/src/paks/portredir/install.sh
>>>>>> new file mode 100644
>>>>>> index 000000000..9f69aeae2
>>>>>> --- /dev/null
>>>>>> +++ b/src/paks/portredir/install.sh
>>>>>> @@ -0,0 +1,32 @@
>>>>>> +#!/bin/bash
>>>>>> +##############################################################
>>>>>> ##############
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +# This file is part of the IPFire
>>>>>> Firewall.                                #
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +# IPFire is free software; you can redistribute it and/or
>>>>>> modify           #
>>>>>> +# it under the terms of the GNU General Public License as
>>>>>> published by     #
>>>>>> +# the Free Software Foundation; either version 2 of the
>>>>>> License, or        #
>>>>>> +# (at your option) any later
>>>>>> version.                                      #
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +# IPFire is distributed in the hope that it will be
>>>>>> useful,                #
>>>>>> +# but WITHOUT ANY WARRANTY; without even the implied warranty
>>>>>> of           #
>>>>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
>>>>>> the            #
>>>>>> +# GNU General Public License for more
>>>>>> details.                             #
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +# You should have received a copy of the GNU General Public
>>>>>> License        #
>>>>>> +# along with IPFire; if not, write to the Free
>>>>>> Software                    #
>>>>>> +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
>>>>>> 02111-1307 USA #
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +# Copyright (C) 2021 IPFire-Team
>>>>>> <info(a)ipfire.org>.                        #
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +##############################################################
>>>>>> ##############
>>>>>> +#
>>>>>> +. /opt/pakfire/lib/functions.sh
>>>>>> +extract_files
>>>>>> +restore_backup ${NAME}
>>>>>> +
>>>>>> +/usr/local/bin/update-lang-cache
>>>>>> +
>>>>>> +chown root:nobody /usr/local/bin/portredirctrl
>>>>>> +chmod 4750 /usr/local/bin/portredirctrl
>>>>>> +chmod u+s /usr/local/bin/portredirctrl
>>>>>> diff --git a/src/paks/portredir/uninstall.sh
>>>>>> b/src/paks/portredir/uninstall.sh
>>>>>> new file mode 100644
>>>>>> index 000000000..df9270125
>>>>>> --- /dev/null
>>>>>> +++ b/src/paks/portredir/uninstall.sh
>>>>>> @@ -0,0 +1,28 @@
>>>>>> +#!/bin/bash
>>>>>> +##############################################################
>>>>>> ##############
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +# This file is part of the IPFire
>>>>>> Firewall.                                #
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +# IPFire is free software; you can redistribute it and/or
>>>>>> modify           #
>>>>>> +# it under the terms of the GNU General Public License as
>>>>>> published by     #
>>>>>> +# the Free Software Foundation; either version 2 of the
>>>>>> License, or        #
>>>>>> +# (at your option) any later
>>>>>> version.                                      #
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +# IPFire is distributed in the hope that it will be
>>>>>> useful,                #
>>>>>> +# but WITHOUT ANY WARRANTY; without even the implied warranty
>>>>>> of           #
>>>>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
>>>>>> the            #
>>>>>> +# GNU General Public License for more
>>>>>> details.                             #
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +# You should have received a copy of the GNU General Public
>>>>>> License        #
>>>>>> +# along with IPFire; if not, write to the Free
>>>>>> Software                    #
>>>>>> +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
>>>>>> 02111-1307 USA #
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +# Copyright (C) 2007 IPFire-Team
>>>>>> <info(a)ipfire.org>.                        #
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +##############################################################
>>>>>> ##############
>>>>>> +#
>>>>>> +. /opt/pakfire/lib/functions.sh
>>>>>> +make_backup ${NAME}
>>>>>> +remove_files
>>>>>> +
>>>>>> +/usr/local/bin/update-lang-cache
>>>>>> diff --git a/src/paks/portredir/update.sh
>>>>>> b/src/paks/portredir/update.sh
>>>>>> new file mode 100644
>>>>>> index 000000000..89c40d0d7
>>>>>> --- /dev/null
>>>>>> +++ b/src/paks/portredir/update.sh
>>>>>> @@ -0,0 +1,26 @@
>>>>>> +#!/bin/bash
>>>>>> +##############################################################
>>>>>> ##############
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +# This file is part of the IPFire
>>>>>> Firewall.                                #
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +# IPFire is free software; you can redistribute it and/or
>>>>>> modify           #
>>>>>> +# it under the terms of the GNU General Public License as
>>>>>> published by     #
>>>>>> +# the Free Software Foundation; either version 2 of the
>>>>>> License, or        #
>>>>>> +# (at your option) any later
>>>>>> version.                                      #
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +# IPFire is distributed in the hope that it will be
>>>>>> useful,                #
>>>>>> +# but WITHOUT ANY WARRANTY; without even the implied warranty
>>>>>> of           #
>>>>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
>>>>>> the            #
>>>>>> +# GNU General Public License for more
>>>>>> details.                             #
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +# You should have received a copy of the GNU General Public
>>>>>> License        #
>>>>>> +# along with IPFire; if not, write to the Free
>>>>>> Software                    #
>>>>>> +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
>>>>>> 02111-1307 USA #
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +# Copyright (C) 2007 IPFire-Team
>>>>>> <info(a)ipfire.org>.                        #
>>>>>> +#                                                             
>>>>>>              #
>>>>>> +##############################################################
>>>>>> ##############
>>>>>> +#
>>>>>> +. /opt/pakfire/lib/functions.sh
>>>>>> +./uninstall.sh
>>>>>> +./install.sh
>>>>>> -- 
>>>>>> 2.18.0
>>>>>> 
>>>>> 
>>>> 
>>> 
>> 
> 


       reply	other threads:[~2021-08-05 20:33 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CD95E831-4AE9-40B7-BB91-27B3F3164270@gmail.com>
2021-08-05 20:33 ` Michael Tremer [this message]
2021-08-06 15:57   ` Stefan Schantl
     [not found] <6EBF1B5C-79B2-4258-B117-C2A4EB16CCFD@gmail.com>
2021-07-05 12:08 ` Stefan Schantl
     [not found] <E41194E1-4002-4960-BF73-F57D6BCCD152@gmail.com>
2021-07-05 12:07 ` Stefan Schantl
     [not found] <ADA23788-C972-417C-8F55-DD9D3B335BE9@gmail.com>
2021-07-01 15:24 ` Michael Tremer
     [not found] <A699ABA7-74D3-4551-A981-E2E3A0935F8E@gmail.com>
2021-07-01  8:08 ` Michael Tremer
     [not found] <305D680D-4D10-4D99-9F1D-3589BDF08FA9@gmail.com>
2021-06-28 17:56 ` Michael Tremer
2021-06-27 13:48 Matthias Fischer
2021-06-28 16:04 ` Michael Tremer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=147F4AEF-0264-4B59-AB39-D87B68883D17@ipfire.org \
    --to=michael.tremer@ipfire.org \
    --cc=development@lists.ipfire.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox