Hey Jon, You probably want “any” as destination. -Michael > On 1 Jul 2021, at 04:08, Jon Murphy 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: > > > > > > > > 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 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 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 >>>>> >>>>> 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 >>>>>> --- >>>>>> 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 >>>>>> # >>>>>> +# >>>>>> # >>>>>> +# 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 "$errormessage "; >>>>>> + &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 "
>>>>> action='$ENV{'SCRIPT_NAME'}'>"; >>>>>> + >>>>>> +print <>>>>> + >>>>>> + >>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> +END >>>>>> + >>>>>> + # create html table with header line 1 >>>>>> + print "
>>>>> bgcolor='$color{'color20'}'>$Lang::tr{'portredir common >>>>>> settings'}
>>>>> class='base'>$Lang::tr{'portredir enable addon'}:>>>>> name='REDIR_ENABLE_ADDON' $checked{'REDIR_ENABLE_ADDON'}{'on'} >>>>>> />
 
>>>>> border='0'>"; >>>>>> + print ""; >>>>>> + if ($netsettings{'GREEN_DEV'}) {print ""; >>>>>> + } else { print ""; } >>>>>> + if ($netsettings{'BLUE_DEV'}) {print ""; >>>>>> + } else { print ""; } >>>>>> + if ($netsettings{'ORANGE_DEV'}) {print ""; >>>>>> + } else { print ""; } >>>>>> + >>>>>> + # the empty right row >>>>>> + print ""; >>>>>> + >>>>>> + # line 2 >>>>>> + print ""; >>>>>> + if ($netsettings{'GREEN_DEV'}) {print "";} else { print >>>>>> "";} >>>>>> + if ($netsettings{'BLUE_DEV'}) {print "";} >>>>>> else { print "";} >>>>>> + if ($netsettings{'ORANGE_DEV'}) {print "";} else { print >>>>>> "";} >>>>>> + >>>>>> + # line 3 >>>>>> + print ""; >>>>>> + if ($netsettings{'GREEN_DEV'}) {print "";} else { print >>>>>> "";} >>>>>> + if ($netsettings{'BLUE_DEV'}) {print "";} >>>>>> else { print "";} >>>>>> + if ($netsettings{'ORANGE_DEV'}) {print "";} else { print >>>>>> "";} >>>>>> + >>>>>> + # line 4 >>>>>> + print ""; >>>>>> + if ($netsettings{'GREEN_DEV'}) {print "";} else { print >>>>>> "";} >>>>>> + if ($netsettings{'BLUE_DEV'}) {print "";} else { print >>>>>> "";} >>>>>> + if ($netsettings{'ORANGE_DEV'}) {print "";} else { print >>>>>> "";} >>>>>> + >>>>>> + print <>>>>> +
>>>>> align='left'>$Lang::tr{'portredir fw for interface'}>>>>> class='base' width='10%'>>>>>> color=green>$Lang::tr{'green'}>>>>> class='base' width='10%'>>>>>> class='base' width='10%'>>>>>> color=blue>$Lang::tr{'blue'}>>>>> class='base' width='10%'>>>>>> class='base' width='10%'>>>>>> color=orange>$Lang::tr{'orange'}>>>>> class='base' width='10%'>>>>>> width='30%'>
$Lang::tr{'portredir force local >>>>>> dns'}>>>>> class='base' align='center'>>>>>> name='REDIR_DNS_GREEN' >>>>>> $checked{'REDIR_DNS_GREEN'}{'on'}>>>>>> class='base' align='center'>>>>>> name='REDIR_DNS_BLUE' $checked{'REDIR_DNS_BLUE'}{'on'}>>>>>> class='base' align='center'>>>>>> name='REDIR_DNS_ORANGE' >>>>>> $checked{'REDIR_DNS_ORANGE'}{'on'}>
$Lang::tr{'portredir force local >>>>>> ntp'}>>>>> class='base' align='center'>>>>>> name='REDIR_NTP_GREEN' >>>>>> $checked{'REDIR_NTP_GREEN'}{'on'}>>>>>> class='base' align='center'>>>>>> name='REDIR_NTP_BLUE' $checked{'REDIR_NTP_BLUE'}{'on'}>>>>>> class='base' align='center'>>>>>> name='REDIR_NTP_ORANGE' >>>>>> $checked{'REDIR_NTP_ORANGE'}{'on'}>
$Lang::tr{'portredir enable user >>>>>> redirections'}>>>>> class='base' align='center'>>>>>> name='REDIR_CUSTOM_GREEN' >>>>>> $checked{'REDIR_CUSTOM_GREEN'}{'on'}>>>>>> class='base' align='center'>>>>>> name='REDIR_CUSTOM_BLUE' >>>>>> $checked{'REDIR_CUSTOM_BLUE'}{'on'}>>>>>> class='base' align='center'>>>>>> name='REDIR_CUSTOM_ORANGE' >>>>>> $checked{'REDIR_CUSTOM_ORANGE'}{'on'}>
>>>>>> + >>>>>> + >>>>>> + >>>>>> +
 
$Lang::tr{'portredir >>>>>> save to activate'}>>>>> type='submit' name='ACTION' value=' $Lang::tr{'save'} >>>>>> '>
>>>>>> +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 >>>>>> + # 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 >>>>>> + } >>>>>> + } else { >>>>>> + # Print notice that currently >>>>>> no ports are redirected. >>>>>> + print "\n"; >>>>>> + print "\n"; >>>>>> + print "\n"; >>>>>> + } >>>>>> + >>>>>> + print "
>>>>> bgcolor='$color{'color20'}' >>>>>> align='center'>$Lang::tr{'interface'}>>>>> bgcolor='$color{'color20'}' >>>>>> align='center'>$Lang::tr{'protocol'}>>>>> bgcolor='$color{'color20'}' >>>>>> align='center'>$Lang::tr{'port'}>>>>> bgcolor='$color{'color20'}' align='center'>$Lang::tr{'ip >>>>>> address'}>>>>> bgcolor='$color{'color20'}' >>>>>> align='center'>$Lang::tr{'remark'}>>>>> bgcolor='$color{'color20'}'>
>>>>> class='base' align='center' $col>>>>>> color=$interface>$Lang::tr{$interface}>>>>> class='base' align='center' $col>$protocol>>>>> class='base' align='center' $col>$port>>>>> class='base' align='center' $col> $address>>>>> class='base' align='center' $col> $remark>>>>> align='center' $col> >>>>>> +
>>>>> method='post' action='$ENV{'SCRIPT_NAME'}'> >>>>>> + >>>>>> >>>>> enable disable'}' /> >>>>>> + >>>>>> >>>>> src='/images/$gif' alt='$gdesc' title='$gdesc' /> >>>>>> + >>>>>> >>>>>> +
>>>>>> +
>>>>> align='center' $col> >>>>>> +
>>>>> method='post' action='$ENV{'SCRIPT_NAME'}'> >>>>>> + >>>>>> >>>>> /> >>>>>> + >>>>>> >>>>> src='/images/edit.gif' alt='$Lang::tr{'edit'}' >>>>>> title='$Lang::tr{'edit'}' /> >>>>>> + >>>>>> >>>>>> +
>>>>>> +
>>>>> align='center' $col> >>>>>> +
>>>>> method='post' name='$key' action='$ENV{'SCRIPT_NAME'}'> >>>>>> + >>>>>> >>>>> src='/images/delete.gif' title='$Lang::tr{'remove'}' >>>>>> alt='$Lang::tr{'remove'}'> >>>>>> + >>>>>> >>>>>> + >>>>>> >>>>> value='$Lang::tr{'remove'}'> >>>>>> +
>>>>>> +
>>>>> colspan='2'>$Lang::tr{'portredir no entries'}
\n"; >>>>>> + >>>>>> + # Section to add new elements or edit existing ones. >>>>>> + print <>>>>> +
>>>>>> +
>>>>>> +
>>>>>> +
>>>>>> + >>>>>> +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 "\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 "\n"; >>>>>> + print "\n"; >>>>>> + } >>>>>> + >>>>>> + print <>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>> action='$ENV{'SCRIPT_NAME'}'> >>>>>> + >>>>> value='$settings{'ID'}'> >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> + >>>>>> +
>>>>> colspan='6'>$Lang::tr{'update'}
>>>>> colspan='11'>$Lang::tr{'dnsforward add a new >>>>>> entry'}
 
>>>>> bgcolor='$color{'color22'}'>>>>>> bgcolor='$color{'color22'}' >>>>>> align='left'>$Lang::tr{'interface'}>>>>> bgcolor='$color{'color22'}' >>>>>> align='left'>$Lang::tr{'protocol'}>>>>> bgcolor='$color{'color22'}' >>>>>> align='left'> $Lang::tr{'port'}>>>>> bgcolor='$color{'color22'}' align='left'> $Lang::tr{'ip >>>>>> address'}>>>>> bgcolor='$color{'color22'}' >>>>>> align='left'> $Lang::tr{'remark'}>>>>> bgcolor='$color{'color22'}'>>>>>> bgcolor='$color{'color22'}'>
>>>>> name='REDIR_ENTRY_PORT' value='$entry_port' >>>>>> size='4'>>>>>> name='REDIR_ENTRY_ADDRESS' value='$entry_address' >>>>>> size='14'>>>>>> name='REDIR_ENTRY_REMARK' value='$entry_remark' >>>>>> size='35'>>>>>> align='center'>
>>>>>> +
>>>>>> +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 >>>>>> # >>>>>> +# >>>>>> # >>>>>> +# 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 >>>>>> +#include >>>>>> +#include >>>>>> +#include >>>>>> +#include >>>>>> +#include >>>>>> +#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 >>>>>> . # >>>>>> +# >>>>>> # >>>>>> +############################################################## >>>>>> ############## >>>>>> +# >>>>>> +. /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 >>>>>> . # >>>>>> +# >>>>>> # >>>>>> +############################################################## >>>>>> ############## >>>>>> +# >>>>>> +. /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 >>>>>> . # >>>>>> +# >>>>>> # >>>>>> +############################################################## >>>>>> ############## >>>>>> +# >>>>>> +. /opt/pakfire/lib/functions.sh >>>>>> +./uninstall.sh >>>>>> +./install.sh >>>>>> -- >>>>>> 2.18.0 >>>>>> >>>>> >>>> >>> >> >