summaryrefslogtreecommitdiffstats
path: root/bin/drakgw
diff options
context:
space:
mode:
Diffstat (limited to 'bin/drakgw')
-rwxr-xr-xbin/drakgw466
1 files changed, 466 insertions, 0 deletions
diff --git a/bin/drakgw b/bin/drakgw
new file mode 100755
index 0000000..78f0b1c
--- /dev/null
+++ b/bin/drakgw
@@ -0,0 +1,466 @@
+#!/usr/bin/perl
+
+#
+# author Guillaume Cottenceau (gc@mandrakesoft.com)
+# modified by Florin Grad (florin@mandrakesoft.com)
+# wizardified by Olivier Blin (oblin@mandriva.com)
+#
+# Copyright 2000-2005 Mandriva
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2, as
+# published by the Free Software Foundation.
+#
+# 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+use strict;
+use lib qw(/usr/lib/libDrakX);
+
+use standalone; #- warning, standalone must be loaded very first, for 'explanations'
+
+use common;
+use detect_devices;
+use interactive;
+use network::network;
+use network::ethernet;
+use run_program;
+use log;
+use c;
+use network::shorewall;
+use network::dhcpd;
+use network::squid;
+use services;
+
+my $sysconf_network = "/etc/sysconfig/network";
+my $masq_file = "$::prefix/etc/shorewall/masq";
+my $cups_conf = "$::prefix/etc/cups/cupsd.conf";
+
+my $in = 'interactive'->vnew('su');
+
+my ($kernel_version) = c::kernel_version() =~ /(...)/;
+unless ($kernel_version >= 2.4) {
+ $in->ask_warn(N("Error"), N("Sorry, we support only 2.4 and above kernels."));
+ $in->exit(-1);
+}
+
+my $net = {};
+network::network::read_net_conf($net);
+my $modules_conf = modules::any_conf->read;
+my %eth_intf = map { $_->[0] => join(': ', $_->[0], $_->[2]) } network::ethernet::get_eth_cards($modules_conf);
+
+my $shorewall = network::shorewall::read();
+my $choice;
+my $gw_enabled;
+my ($net_interface_name, $lan_interface_name, $lan_intf, $internal_domain_name);
+my $use_dhcpd = 1;
+my $use_caching_dns = 1;
+my $use_caching_proxy = 1;
+
+my $resolv_conf = network::network::read_resolv_conf_raw();
+my $squid_conf = network::squid::read_squid_conf();
+my $dhcpd_conf = network::dhcpd::read_dhcpd_conf();
+
+require wizards;
+my $wiz = wizards->new(
+ {
+ defaultimage => "drakgw.png",
+ name => N("Internet Connection Sharing"),
+ pages => {
+ welcome =>
+ {
+ name => N("You are about to configure your computer to share its Internet connection.
+With that feature, other computers on your local network will be able to use this computer's Internet connection.
+
+Make sure you have configured your Network/Internet access using drakconnect before going any further.
+
+Note: you need a dedicated Network Adapter to set up a Local Area Network (LAN)."),
+ post => sub {
+ $gw_enabled = !$shorewall->{disabled} && grep { !/^#/ } cat_($masq_file);
+ return $gw_enabled ? "ask_reconfigure" : "choose_net_interface";
+ },
+ },
+
+ ask_reconfigure =>
+ {
+ name => sub {
+ $gw_enabled ?
+ N("The setup of Internet Connection Sharing has already been done.
+It's currently enabled.
+
+What would you like to do?") :
+ N("The setup of Internet connection sharing has already been done.
+It's currently disabled.
+
+What would you like to do?"); #- FIXME : not used for now
+ },
+ data => sub {
+ [ { type => "list", val => \$choice, list => [ ($gw_enabled ? N_("Disable") : N_("Enable")), N_("Reconfigure") ], format => \&translate } ];
+ },
+ post => sub {
+ if ($choice eq "Enable") {
+ #- FIXME, not used for now
+ #- gw_enable();
+ return "end_enabled";
+ } elsif ($choice eq "Disable") {
+ gw_disable();
+ return "end_disabled";
+ } elsif ($choice eq "Reconfigure") {
+ return "choose_net_interface";
+ }
+ },
+ },
+
+ choose_net_interface =>
+ {
+ pre => sub {
+ $net_interface_name = $shorewall->{net_interface};
+ },
+ name => translate($network::shorewall::ask_shorewall_interface_label),
+ data => network::shorewall::shorewall_interface_choices(\$net_interface_name),
+ post => sub {
+ network::shorewall::set_net_interface($shorewall, $net_interface_name);
+ my $locals = @{$shorewall->{loc_interface}};
+ if ($locals == 0) {
+ return "end_no_lan_interface";
+ } elsif ($locals == 1) {
+ $lan_interface_name = $shorewall->{loc_interface}[0];
+ return "one_lan_interface";
+ } else {
+ return "choose_lan_interface";
+ }
+ },
+ },
+
+ one_lan_interface =>
+ {
+ name => sub {
+ N("There is only one configured network adapter on your system:
+
+%s
+
+I am about to setup your Local Area Network with that adapter.", format_interfaces($lan_interface_name));
+ },
+ next => "lan_configure",
+ },
+
+ choose_lan_interface =>
+ {
+ name => N("Please choose what network adapter will be connected to your Local Area Network."),
+ data => sub {
+ [ { type => "list", val => \$lan_interface_name, list => $shorewall->{loc_interface}, format => \&format_interfaces } ];
+ },
+ post => sub {
+ log::explanations("Choosing network device: $lan_interface_name");
+ "lan_configure";
+ },
+ },
+
+ lan_configure =>
+ {
+ pre => sub {
+ $lan_intf = $net->{ifcfg}{$lan_interface_name} ||= {};
+ $lan_intf->{DEVICE} = $lan_interface_name;
+ $lan_intf->{ONBOOT} = 'yes';
+ $lan_intf->{BOOTPROTO} = 'static';
+ $lan_intf->{IPADDR} ||= "192.168.1.1";
+ $lan_intf->{NETMASK} ||= "255.255.255.0";
+ $internal_domain_name = $resolv_conf->{search}[0] ||= "homeland.net";
+ },
+ name => N("Local Area Network settings"),
+ data => sub {
+ [
+ { label => N("Local IP address"), val => \$lan_intf->{IPADDR} },
+ { label => N("Netmask"), val => \$lan_intf->{NETMASK} },
+ { label => N("The internal domain name"), val => \$internal_domain_name },
+ ];
+ },
+ complete => sub {
+ network::network::update_broadcast_and_network($lan_intf);
+ if (my $conflict = find { $_->{NETWORK} eq $lan_intf->{NETWORK} } grep { $_->{DEVICE} ne $lan_intf->{DEVICE} } values %{$net->{ifcfg}}) {
+ $in->ask_warn(N("Error"), N("Potential LAN address conflict found in current config of %s!\n", $conflict->{DEVICE}));
+ return 1;
+ }
+ 0;
+ },
+ post => sub {
+ network::network::configure_network($net, $in, $modules_conf) unless $::testing;
+ return "dns";
+ },
+ },
+
+ dns =>
+ {
+ pre => sub {
+ $dhcpd_conf->{domain_name_servers}[0] = $resolv_conf->{nameserver}[0] ||= $lan_intf->{IPADDR};
+ },
+ name => N("Domain Name Server (DNS) configuration"),
+ data => sub {
+ my @disable = (disabled => sub { $use_caching_dns });
+ [
+ { text => N("Use this gateway as domain name server"), val => \$use_caching_dns, type => 'bool' },
+ { label => N("The DNS Server IP"), val => \$dhcpd_conf->{domain_name_servers}[0], @disable },
+ ];
+ },
+ complete => sub {
+ !$use_caching_dns || $::testing and return 0;
+ #- install a caching name server if the specified DNS is the gateway
+ !$in->do_pkgs->ensure_is_installed('caching-nameserver', '/var/named/named.local');
+ },
+ post => sub {
+ services::set_status($_, $use_caching_dns) foreach qw(named caching-nameserver);
+ return "dhcpd";
+ },
+ },
+
+ dhcpd =>
+ {
+ pre => sub {
+ #- not editable
+ $dhcpd_conf->{option_routers}[0] = $lan_intf->{IPADDR};
+ $dhcpd_conf->{subnet_mask}[0] = $lan_intf->{NETMASK};
+ $dhcpd_conf->{domain_name}[0] = $internal_domain_name;
+ #- editable
+ $dhcpd_conf->{dynamic_bootp}[0] ||= "16";
+ $dhcpd_conf->{dynamic_bootp}[1] ||= "253";
+ $dhcpd_conf->{default_lease_time}[0] ||= "21600";
+ $dhcpd_conf->{max_lease_time}[0] ||= "43200";
+ },
+ name => N("DHCP Server Configuration.
+
+Here you can select different options for the DHCP server configuration.
+If you do not know the meaning of an option, simply leave it as it is."),
+ data => sub {
+ my @advanced_disable = (advanced => 1, disabled => sub { !$use_dhcpd });
+ [
+ { text => N("Use automatic configuration (DHCP)"), val => \$use_dhcpd, type => 'bool' },
+ { label => N("The DHCP start range"), val => \$dhcpd_conf->{dynamic_bootp}[0], @advanced_disable },
+ { label => N("The DHCP end range"), val => \$dhcpd_conf->{dynamic_bootp}[1], @advanced_disable },
+ { label => N("The default lease (in seconds)"), val => \$dhcpd_conf->{default_lease_time}[0], @advanced_disable },
+ { label => N("The maximum lease (in seconds)"), val => \$dhcpd_conf->{max_lease_time}[0], @advanced_disable }
+ ];
+ },
+ complete => sub {
+ !$use_dhcpd || $::testing and return 0;
+ $in->do_pkgs->ensure_is_installed('dhcp-server', '/usr/sbin/dhcpd') or return 1;
+ 0;
+ },
+ post => sub {
+ network::dhcpd::write_dhcpd_conf($dhcpd_conf, $lan_intf->{DEVICE}) if $use_dhcpd;
+ services::set_status("dhcpd", $use_dhcpd);
+ return "proxy";
+ }
+ },
+
+ proxy =>
+ {
+ pre => sub {
+ $squid_conf->{http_port}[0] ||= "3128";
+ $squid_conf->{cache_size}[1] ||= "100";
+ $squid_conf->{admin_mail}[0] ||= 'admin@mydomain.com';
+ $squid_conf->{visible_hostname}[0] ||= 'myfirewall@mydomain.com';
+ },
+ name => N("Proxy caching server (SQUID)"),
+ data => sub {
+ my @disable = (advanced => 1, disabled => sub { !$use_caching_proxy });
+ [
+ { text => N("Use this gateway as proxy caching server"), val => \$use_caching_proxy, type => 'bool' },
+ { label => N("Admin mail"), val => \$squid_conf->{admin_mail}[0], @disable },
+ { label => N("Visible hostname"), val => \$squid_conf->{visible_hostname}[0], @disable },
+ { label => N("Proxy port"), val => \$squid_conf->{http_port}[0], advanced => 1, @disable },
+ { label => N("Cache size (MB)"), val => \$squid_conf->{cache_size}[1], advanced => 1, @disable },
+ ];
+ },
+ complete => sub {
+ !$use_caching_proxy || $::testing and return 0;
+ $in->do_pkgs->ensure_is_installed('squid', '/usr/sbin/squid') or return 1;
+ 0;
+ },
+ post => sub {
+ network::squid::write_squid_conf($squid_conf, $lan_intf, $internal_domain_name) if $use_caching_proxy;
+ services::set_status("squid", $use_caching_proxy);
+ if ($use_caching_proxy) {
+ set_proxy_port($squid_conf->{http_port}[0]);
+ } else {
+ delete_proxy_ports();
+ }
+ -f $cups_conf ? "cups" : end_step();
+ },
+ },
+
+ cups =>
+ {
+ name => N("Broadcast printer information"),
+ type => "yesorno",
+ default => "yes",
+ post => sub {
+ update_cups() unless $::testing;
+ end_step();
+ },
+ },
+
+ end_no_lan_interface =>
+ {
+ name => N("No ethernet network adapter has been detected on your system. Please run the hardware configuration tool."),
+ end => 1,
+ },
+
+ end_enabled =>
+ {
+ name => N("Internet Connection Sharing is now enabled."),
+ end => 1,
+ },
+
+ end_disabled =>
+ {
+ name => N("Internet Connection Sharing is now disabled."),
+ end => 1,
+ },
+
+ end =>
+ {
+ name => N("Everything has been configured.
+You may now share Internet connection with other computers on your Local Area Network, using automatic network configuration (DHCP) and
+ a Transparent Proxy Cache server (SQUID)."),
+ end => 1,
+ },
+ },
+});
+$wiz->safe_process($in);
+
+
+
+sub format_interfaces {
+ my ($interface) = @_;
+ $eth_intf{$interface} || $interface;
+}
+
+sub end_step() {
+ gw_configure();
+ log::l("[drakgw] Installation complete, exiting");
+ "end";
+}
+
+sub delete_proxy_ports() {
+ my $r = $shorewall->{redirects}{tcp};
+ my @ports = grep { $r->{$_} eq 'www' } keys %$r;
+ delete $r->{$_} foreach @ports;
+}
+
+sub set_proxy_port {
+ my ($port) = @_;
+ $shorewall->{redirects}{tcp}{$port} = 'www';
+}
+
+sub gw_disable() {
+ my $_wait_disabl = $in->wait_message('', N("Disabling servers..."));
+ return if $::testing;
+ services::set_status($_, 0) foreach qw(dhcpd squid named);
+ delete_proxy_ports();
+ network::shorewall::write($shorewall);
+ foreach ($network::dhcpd::dhcpd_conf_file, $network::squid::squid_conf_file, $masq_file) {
+ if (-f $_) { rename($_, "$_.drakgwdisable") or die "Could not rename $_ to $_.drakgwdisable" }
+ }
+ services::restart("shorewall");
+}
+
+sub gw_configure() {
+ #- test for potential conflict with previous firewall config
+ if (network::shorewall::check_iptables()) {
+ $in->ask_warn(N("Firewalling configuration detected!"),
+ N("Warning! An existing firewalling configuration has been detected. You may need some manual fixes after installation."));
+ }
+
+ $in->do_pkgs->ensure_is_installed('shorewall', '/sbin/shorewall') or $in->exit(-1);
+
+ my $_wait_configuring = $in->wait_message(N("Configuring..."),
+ N("Configuring firewall..."));
+
+ $shorewall->{disabled} = 0;
+ $shorewall->{masq_subnet} = "$lan_intf->{NETWORK}/$lan_intf->{NETMASK}";
+ network::shorewall::write($shorewall);
+
+ #- be sure that FORWARD_IPV4 is enabled in /etc/sysconfig/network
+ log::explanations("Enabling IPV4 forwarding");
+ substInFile { s/^FORWARD_IPV4.*\n//; $_ .= "FORWARD_IPV4=true\n" if eof } $sysconf_network if !$::testing;
+ services::restart("network");
+}
+
+sub update_cups() {
+ #- Set up /etc/cups/cupsd.conf to make the broadcasting of the printer info
+ #- working correctly:
+ #-
+ #- 1. ServerName <server's IP address> # because clients do necessarily
+ #- # know the server's name
+ #-
+ #- 2. BrowseAddress <server's Broadcast IP> # broadcast printer info into
+ #- # the local network.
+ #-
+ #- 3. BrowseOrder Deny,Allow
+ #- BrowseDeny All
+ #- BrowseAllow <IP mask for local net> # Only accept broadcast signals
+ #- # coming from local network
+ #-
+ #- 4. <Location />
+ #- Order Deny,Allow
+ #- Deny From All
+ #- Allow From <IP mask for local net> # Allow only machines of local
+ #- </Location> # network to access the server
+ #-
+ #- These steps are only done when the CUPS package is installed.
+
+ #- Modify the root location block in /etc/cups/cupsd.conf
+
+ log::explanations("Updating CUPS configuration accordingly");
+
+ substInFile {
+ s/^ServerName[^:].*\n//; $_ .= "ServerName $lan_intf->{IPADDR}\n" if eof;
+ s/^BrowseAddress.*\n//; $_ .= "BrowseAddress $lan_intf->{BROADCAST}\n" if eof;
+ s/^BrowseOrder.*\n//; $_ .= "BrowseOrder Deny,Allow\n" if eof;
+ s/^BrowseDeny.*\n//; $_ .= "BrowseDeny All\n" if eof;
+ s/^BrowseAllow.*\n//; $_ .= "BrowseAllow \@IF($lan_interface_name)\n" if eof;
+ } $cups_conf;
+
+ my @cups_conf_content = cat_($cups_conf);
+ my @root_location; my $root_location_start; my $root_location_end;
+
+ # Cut out the root location block so that it can be treated seperately
+ # without affecting the rest of the file
+ if (any { m|^\s*<Location\s+/\s*>| } @cups_conf_content) {
+ $root_location_start = -1;
+ $root_location_end = -1;
+ # Go through all the lines, bail out when start and end line found
+ for (my $i = 0; $i < @cups_conf_content && $root_location_end == -1; $i++) {
+ if ($cups_conf_content[$i] =~ m|^\s*<\s*Location\s+/\s*>|) {
+ $root_location_start = $i;
+ } elsif ($cups_conf_content[$i] =~ m|^\s*<\s*/Location\s*>| && $root_location_start != -1) {
+ $root_location_end = $i;
+ }
+ }
+ # Rip out the block and store it seperately
+ @root_location = splice(@cups_conf_content, $root_location_start, $root_location_end - $root_location_start + 1);
+ } else {
+ # If there is no root location block, create one
+ $root_location_start = @cups_conf_content;
+ @root_location = ("<Location />\n", "</Location>\n");
+ }
+
+ # Delete all former "Order", "Allow", and "Deny" lines from the root location block
+ s/^\s*Order.*//, s/^\s*Allow.*//, s/^\s*Deny.*// foreach @root_location;
+
+ # Add the new "Order" and "Deny" lines, add an "Allow" line for the local network
+ splice(@root_location, -1, 0, $_) foreach "Order Deny,Allow\n", "Deny From All\n", "Allow From 127.0.0.1\n",
+ "Allow From \@IF($lan_interface_name)\n";
+
+ # Put the changed root location block back into the file
+ splice(@cups_conf_content, $root_location_start, 0, @root_location);
+
+ output $cups_conf, @cups_conf_content;
+}