From: Marcel Lorenz marcel.lorenz@ipfire.org
Please note: This is a new addon written by Marcel Lorenz marcel.lorenz@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.
Signed-off-by: Matthias Fischer matthias.fischer@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@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_INTERFACE'}} = 'selected'; +$selected{'REDIR_ENTRY_PROTOCOL'}{$settings{'REDIR_ENTRY_PROTOCOL'}} = '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@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@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@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@ipfire.org. # +# # +############################################################################ +# +. /opt/pakfire/lib/functions.sh +./uninstall.sh +./install.sh