From: Michael Tremer <michael.tremer@ipfire.org>
To: development@lists.ipfire.org
Subject: Re: [PATCH] New addon: Portredirect 1.0
Date: Thu, 01 Jul 2021 16:24:11 +0100 [thread overview]
Message-ID: <56118375-8C9D-4553-A919-6696E7944E8D@ipfire.org> (raw)
In-Reply-To: <ADA23788-C972-417C-8F55-DD9D3B335BE9@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 78729 bytes --]
@Stefan: There should be an exception in the UI that these rules can be created when REDIRECT is being used.
> On 1 Jul 2021, at 16:04, Jon Murphy <jcmurphy26(a)gmail.com> wrote:
>
>> You probably want “any” as destination.
>
> Those are the only choices that allow a Save. When I enter an IP address I get this error:
>
>
> Error messages
>
> Source and destination IP addresses are from the same subnet.
>
>
>
> Jon
>
>> On Jul 1, 2021, at 3:08 AM, Michael Tremer <michael.tremer(a)ipfire.org> wrote:
>>
>> Hey Jon,
>>
>> You probably want “any” as destination.
>>
>> -Michael
>>
>>> On 1 Jul 2021, at 04:08, Jon Murphy <jcmurphy26(a)gmail.com> wrote:
>>>
>>> Hi Stefan,
>>>
>>> Thank you for taking this on!
>>>
>>> I applied the patchwork.ipfire patch.
>>>
>>> I think I entered something wrong since I cannot get things to work. I tried both with Destination Firewall GREEN & Firewall RED.
>>>
>>>
>>> Does the Firewall Rule seem right?
>>>
>>> Best regards,
>>> Jon
>>>
>>>
>>> Here is the rule I set up:
>>>
>>>
>>> <Screen Shot 2021-06-30 at 9.53.52 PM.png>
>>>
>>> <Screen Shot 2021-06-30 at 9.53.10 PM.png>
>>>
>>>
>>> And this is what I see with conntrack:
>>>
>>> conntrack -E -e NEW,UPDATE | grep -e "=53 "
>>>
>>> [NEW] udp 17 30 src=192.168.1.102 dst=1.2.3.4 sport=51169 dport=53 [UNREPLIED] src=1.2.3.4 dst=10.7.4.10 sport=53 dport=51169
>>> [NEW] udp 17 30 src=192.168.1.102 dst=1.2.3.4 sport=54168 dport=53 [UNREPLIED] src=1.2.3.4 dst=10.7.4.10 sport=53 dport=54168
>>> [NEW] udp 17 30 src=192.168.1.102 dst=1.2.3.4 sport=56094 dport=53 [UNREPLIED] src=1.2.3.4 dst=10.7.4.10 sport=53 dport=56094
>>> [NEW] udp 17 30 src=192.168.1.102 dst=1.2.3.4 sport=52964 dport=53 [UNREPLIED] src=1.2.3.4 dst=10.7.4.10 sport=53 dport=52964
>>> [NEW] udp 17 30 src=192.168.1.102 dst=1.2.3.4 sport=53279 dport=53 [UNREPLIED] src=1.2.3.4 dst=10.7.4.10 sport=53 dport=53279
>>> [NEW] udp 17 30 src=192.168.1.102 dst=1.2.3.4 sport=61657 dport=53 [UNREPLIED] src=1.2.3.4 dst=10.7.4.10 sport=53 dport=61657
>>> [NEW] udp 17 30 src=192.168.1.102 dst=1.2.3.4 sport=57723 dport=53 [UNREPLIED] src=1.2.3.4 dst=10.7.4.10 sport=53 dport=57723
>>>
>>>
>>>
>>>
>>>> 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 </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'> </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'> </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> $address</td>
>>>>>>>> + <td width='40%'
>>>>>>>> class='base' align='center' $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='$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> </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'> <b>$Lang::tr{'port'}</b></td>
>>>>>>>> + <td class='base' width='13%'
>>>>>>>> bgcolor='$color{'color22'}' align='left'> <b>$Lang::tr{'ip
>>>>>>>> address'}</b></td>
>>>>>>>> + <td class='base' width='30%'
>>>>>>>> bgcolor='$color{'color22'}'
>>>>>>>> align='left'> <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
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>
next parent reply other threads:[~2021-07-01 15:24 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <ADA23788-C972-417C-8F55-DD9D3B335BE9@gmail.com>
2021-07-01 15:24 ` Michael Tremer [this message]
[not found] <CD95E831-4AE9-40B7-BB91-27B3F3164270@gmail.com>
2021-08-05 20:33 ` Michael Tremer
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] <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=56118375-8C9D-4553-A919-6696E7944E8D@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