#!/usr/bin/perl # # Guillaume Cottenceau (gc@mandrakesoft.com) # # Copyright 2000 MandrakeSoft # # This software may be freely redistributed under the terms of the GNU # public license. # # 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., 675 Mass Ave, Cambridge, MA 02139, USA. # use lib qw(/usr/lib/libDrakX); use common qw(:common :system :file); use interactive; use standalone; use log; use c; use netconnect; use detect_devices; $::isInstall and die "Not supported during install.\n"; $::isEmbedded = ($::XID, $::CCPID) = "@ARGV" =~ /--embedded (\w+) (\w+)/; local $_ = join '', @ARGV; /-h/ and die "usage: drakgw [--version]\n"; /-version/ and die 'version: $Id$ '."\n"; $::isEmbedded or $::isWizard = 1; $::direct = /-direct/; my $sysconf_network = "/etc/sysconfig/network"; my $conf_linuxconf = "/etc/conf.linuxconf"; my $rc_firewall_generic = "/etc/rc.d/rc.firewall"; my $rc_firewall_22 = "/etc/rc.d/rc.firewall.inet_sharing-2.2"; my $rc_firewall_24 = "/etc/rc.d/rc.firewall.inet_sharing-2.4"; my $dhcpd_conf = "/etc/dhcpd.conf"; my $cups_conf = "/etc/cups/cupsd.conf"; my $drakgw_setup = "/etc/sysconfig/inet_sharing"; my ($kernel_version) = c::kernel_version() =~ /(...)/; log::l("[drakgw] kernel_version $kernel_version"); $kernel_version eq '2.2' || $kernel_version eq '2.4' or die "Only for 2.2 or 2.4 kernels.\n"; my $in = interactive::vnew('su'); sub sys { system(@_) == 0 or die "sys: $_[0]" } sub start_daemons() { my $cups_used = 0; log::l("[drakgw] Starting daemons"); if (-f "/etc/rc.d/init.d/cups") { if (grep(/is running/, `/etc/rc.d/init.d/cups status`)) { $cups_used = 1; sys("/etc/rc.d/init.d/cups stop"); } } grep(/is running/, `/etc/rc.d/init.d/dhcpd status 2> /dev/null`) and sys("/etc/rc.d/init.d/dhcpd stop"); grep(/connection refused/, `/etc/rc.d/init.d/named status 2> /dev/null`) or sys("/etc/rc.d/init.d/named stop"); sys("/etc/rc.d/init.d/network restart"); sys("sh $rc_firewall_generic"); sys("/etc/rc.d/init.d/$_ start"), sys("/sbin/chkconfig --level 345 $_ on") foreach 'named', 'dhcpd'; sys("/etc/rc.d/init.d/cups start") if $cups_used; output $drakgw_setup, "INET_SHARING=enabled\n"; } sub stop_daemons() { log::l("[drakgw] Stopping daemons"); grep /is running/, `/etc/rc.d/init.d/dhcpd status` and sys("/etc/rc.d/init.d/dhcpd stop"); grep /Connection refused/, `/etc/rc.d/init.d/named status 2>&1` or sys("/etc/rc.d/init.d/named stop"); if ($kernel_version eq "2.2") { sys("/sbin/ipchains -F"); } else { sys("/sbin/iptables -t nat -F"); } sys("/sbin/chkconfig --level 345 $_ off") foreach 'named', 'dhcpd'; output $drakgw_setup, "INET_SHARING=disabled\n"; } sub fatal_quit($) { log::l("[drakgw] FATAL: $_[0]"); undef $wait_configuring; $in->ask_warn('', $_[0]); quit_global($in, -1); } while ($::isEmbedded) { kill USR2, $::CCPID; my $setup_state = grep(/disabled/, cat_($drakgw_setup)) ? _("The setup has already been done, but it's currently disabled.") : grep(/enabled/, cat_($drakgw_setup)) ? _("The setup has already been done, and it's currently enabled.") : _("No Internet Connection Sharing has ever been configured."); $in->ask_okcancel('', _("Welcome to the Internet Connection Sharing utility! %s Click on ``Ok'' if you want to launch the setup wizard.", $setup_state)) and system("/usr/sbin/drakgw"); kill USR1, $::CCPID; } begin: #- ********************************** #- * 0th step: verify if we are already set up if (-f $drakgw_setup) { $::Wizard_no_previous = 1; if (grep(/enabled/, cat_($drakgw_setup))) { my $r = $in->ask_from_list_(_("Internet Connection Sharing currently enabled"), _("The setup of Internet connection sharing has already been done. It's currently enabled. What would you like to do?"), [ __("disable"), __("reconfigure"), __("dismiss") ]) or quit_global($in, 0); if ($r eq "disable") { { my $wait_disabl = $in->wait_message('', _("Disabling servers...")); stop_daemons(); } foreach ($dhcpd_conf, $rc_firewall_22, $rc_firewall_24) { renamef($_, "$_.drakgwdisable") or die "Could not rename $_ to $_.drakgwdisable" } log::l("[drakgw] Disabled"); $::Wizard_finished = 1; $in->ask_okcancel('', _("Internet connection sharing is now disabled.")); quit_global($in, 0); } if ($r eq "dismiss") { quit_global($in, 0); } } elsif (grep(/disabled/, cat_($drakgw_setup))) { my $r = $in->ask_from_list_(_("Internet Connection Sharing currently disabled"), _("The setup of Internet connection sharing has already been done. It's currently disabled. What would you like to do?"), [ __("enable"), __("reconfigure"), __("dismiss") ]); if ($r eq "enable") { foreach ($dhcpd_conf, $rc_firewall_22, $rc_firewall_24) { rename($_, "$_.old") if -f $_; rename("$_.drakgwdisable", $_) or die "Could not find configuration. Please reconfigure."; } { my $wait_enabl = $in->wait_message('', _("Enabling servers...")); start_daemons(); } log::l("[drakgw] Enabled"); $::Wizard_finished = 1; $in->ask_okcancel('', _("Internet connection sharing is now enabled.")); quit_global($in, 0); } if ($r eq "dismiss") { quit_global($in, 0); } } else { $in->ask_warn(_("Unrecognized config file"), _("Config file content could not be interpreted.")); quit_global($in, -1); } } #- ********************************** #- * 1st step: detect/setup step_ask_confirm: $::Wizard_no_previous = 1; $::direct or $in->ask_okcancel(_("Internet Connection Sharing"), _("You are about to configure your computer to share its Internet connection. Note: you need a dedicated Network Adapter to set up a Local Area Network (LAN)."), 1) or quit_global($in, 0); undef $::Wizard_no_previous; step_detectsetup: my @configured_devices = map { /ifcfg-(\S+)/ } `ls /etc/sysconfig/network-scripts/ifcfg*`; my %aliased_devices; /^\s*alias\s+(eth[0-9])\s+(\S+)/ and $aliased_devices{$1} = $2 foreach cat_("/etc/modules.conf"); my $card_netconnect = netconnect::get_net_device(); defined $card_netconnect and log::l("[drakgw] Information from netconnect: ignore card $card_netconnect"); my @cards = grep { log::l("[drakgw] Have network card: $_"); $_ ne $card_netconnect } detect_devices::getNet(); log::l("[drakgw] Available network cards: ", join(", ", @cards)); my $format = sub { $aliased_devices{$_[0]} ? _("Interface %s (using module %s)", $_[0], $aliased_devices{$_[0]}) : _("Interface %s", $_[0]); }; #- setup the network interface we shall use my $device; if (!@cards) { $in->ask_warn(_("No network adapter on your system!"), _("No ethernet network adapter has been detected on your system. Please run the hardware configuration tool.")); quit_global($in); } elsif (@cards == 1) { $device = $cards[0]; print "device $device\n"; my $t = $format->($device); print "format $t\n"; $in->ask_okcancel(_("Network interface"), _("There is only one configured network adapter on your system: %s I am about to setup your Local Area Network with that adapter.", $format->($device)), 1) or goto step_ask_confirm; } else { $device = $in->ask_from_listf(_("Choose the network interface"), _("Please choose what network adapter will be connected to your Local Area Network."), $format, \@cards, ) or goto step_ask_confirm; defined $device or quit_global($in); } log::l("[drakgw] Choosing network card: $device\n"); grep(/$device/, @configured_devices) and ($in->ask_okcancel('', _("Warning, the network adapter is already configured. I will reconfigure it.")) or goto step_detectsetup); my $lan_address = "192.168.0"; #- test for potential conflict with other networks foreach (grep { $_ ne $device } @configured_devices) { grep(/$lan_address/, cat_("/etc/sysconfig/network-scripts/ifcfg-$_")) and ($in->ask_warn('', _("Potential LAN address conflict found in current config of $_!\n")) or goto step_detectsetup); } #- test for potential conflict with previous firewall config if ($kernel_version eq '2.2') { if (-f '/etc/sysconfig/ipchains' || -x '/sbin/ipchains' && listlength(`/sbin/ipchains -nL`) > 3) { $in->ask_okcancel(_("Firewalling configuration detected!"), _("Warning! An existing firewalling configuration has been detected. You may need some manual fix after installation.")) or goto step_detectsetup; } } else { system('modprobe iptable_nat'); if (-f '/etc/sysconfig/iptables' || -x '/sbin/iptables' && listlength(`/sbin/iptables -t nat -nL`) > 8) { $in->ask_okcancel(_("Firewalling configuration detected!"), _("Warning! An existing firewalling configuration has been detected. You may need some manual fix after installation.")) or goto step_detectsetup; } } #- ********************************** #- * 2nd step: configure $wait_configuring = $in->wait_message(_("Configuring..."), _("Configuring scripts, installing software, starting servers...")); #- setup the /etc/sysconfig/network-script/ script my $network_scripts = "/etc/sysconfig/network-scripts"; my $ifcfg = "$network_scripts/ifcfg-$device"; renamef($ifcfg, "$network_scripts/old.ifcfg-$device"); output($ifcfg, qq(DEVICE=$device BOOTPROTO=static IPADDR=$lan_address.1 NETMASK=255.255.255.0 NETWORK=$lan_address.0 BROADCAST=$lan_address.255 ONBOOT=yes )); #- install and setup the RPM packages my $rpms_to_install; my %rpm2file = ( ipchains => "/sbin/ipchains", iptables => "/sbin/iptables", dhcp => "/usr/sbin/dhcpd", linuxconf => $conf_linuxconf, bind => "/usr/sbin/named", "caching-nameserver" => "/var/named/named.local"); $in->standalone::pkgs_install(grep { !-e $rpm2file{$_} } keys %rpm2file); -e $rpm2file{$_} or fatal_quit(_("Problems installing package $_")) foreach keys %rpm2file; #- setup the masquerading configuration if (!-f $rc_firewall_generic || !grep(/drakgw/, cat_($rc_firewall_generic))) { output($rc_firewall_generic, q(#!/bin/sh # # Automatically generated by drakgw KERNELMAJ=`uname -r | sed -e 's,\..*,,'` KERNELMIN=`uname -r | sed -e 's,[^\.]*\.,,' -e 's,\..*,,'` if [ "$KERNELMAJ" -eq 2 -a "$KERNELMIN" -eq 2 ]; then [ -x ) . $rc_firewall_22 . ' ] && ' . $rc_firewall_22 . q( fi if [ "$KERNELMAJ" -eq 2 -a "$KERNELMIN" -eq 4 ]; then [ -x ) . $rc_firewall_24 . ' ] && ' . $rc_firewall_24 . q( fi )); } chmod 0700, $rc_firewall_generic; output($rc_firewall_22, qq(#!/bin/sh # # rc.firewall - Initial SIMPLE IP Masquerade test for 2.1.x and 2.2.x kernels using IPCHAINS # # Load all required IP MASQ modules # # NOTE: Only load the IP MASQ modules you need. All current IP MASQ modules # are shown below but are commented out from loading. # Needed to initially load modules # /sbin/depmod -a # Supports the proper masquerading of FTP file transfers using the PORT method # /sbin/modprobe ip_masq_ftp # Supports the masquerading of RealAudio over UDP. Without this module, # RealAudio WILL function but in TCP mode. This can cause a reduction # in sound quality # /sbin/modprobe ip_masq_raudio # Supports the masquerading of IRC DCC file transfers # /sbin/modprobe ip_masq_irc # Supports the masquerading of Quake and QuakeWorld by default. This modules is # for for multiple users behind the Linux MASQ server. If you are going to play # Quake I, II, and III, use the second example. # # NOTE: If you get ERRORs loading the QUAKE module, you are running an old # ----- kernel that has bugs in it. Please upgrade to the newest kernel. # #Quake I / QuakeWorld (ports 26000 and 27000) #/sbin/modprobe ip_masq_quake # #Quake I/II/III / QuakeWorld (ports 26000, 27000, 27910, 27960) /sbin/modprobe ip_masq_quake 26000,27000,27910,27960 # Supports the masquerading of the CuSeeme video conferencing software # /sbin/modprobe ip_masq_cuseeme #Supports the masquerading of the VDO-live video conferencing software # /sbin/modprobe ip_masq_vdolive #CRITICAL: Enable IP forwarding since it is disabled by default since # # Redhat Users: you may try changing the options in /etc/sysconfig/network from: # # FORWARD_IPV4=false # to # FORWARD_IPV4=true # echo 1 > /proc/sys/net/ipv4/ip_forward # Dynamic IP users: # # If you get your IP address dynamically from SLIP, PPP, or DHCP, enable this following # option. This enables dynamic-ip address hacking in IP MASQ, making the life # with Diald and similar programs much easier. # #echo 1 > /proc/sys/net/ipv4/ip_dynaddr # MASQ timeouts # # 2 hrs timeout for TCP session timeouts # 10 sec timeout for traffic after the TCP/IP "FIN" packet is received # 160 sec timeout for UDP traffic (Important for MASQ'ed ICQ users) # /sbin/ipchains -M -S 7200 10 160 # DHCP: For people who receive their external IP address from either DHCP or BOOTP # such as ADSL or Cablemodem users, it is necessary to use the following # before the deny command. The "bootp_client_net_if_name" should be replaced # the name of the link that the DHCP/BOOTP server will put an address on to? # This will be something like "eth0", "eth1", etc. # # This example is currently commented out. # # #/sbin/ipchains -A input -j ACCEPT -i bootp_clients_net_if_name -s 0/0 67 -d 0/0 68 -p udp # Enable simple IP forwarding and Masquerading # # NOTE: The following is an example for an internal LAN address in the 192.168.0.x # network with a 255.255.255.0 or a "24" bit subnet mask. # # Please change this network number and subnet mask to match your internal LAN setup # /sbin/ipchains -P forward DENY /sbin/ipchains -A forward -s $lan_address.0/24 -j MASQ )); chmod 0700, $rc_firewall_22; output($rc_firewall_24, qq(#!/bin/sh # Load the NAT module (this pulls in all the others). modprobe iptable_nat # Turn on IP forwarding echo 1 > /proc/sys/net/ipv4/ip_forward # In the NAT table (-t nat), Append a rule (-A) after routing (POSTROUTING) # which says to MASQUERADE the connection (-j MASQUERADE). iptables -t nat -A POSTROUTING -s $lan_address.0/24 -j MASQUERADE )); chmod 0700, $rc_firewall_24; #- be sure that FORWARD_IPV4 is enabled in /etc/sysconfig/network substInFile { s/^FORWARD_IPV4.*\n//; $_ .= "FORWARD_IPV4=true\n" if eof } $sysconf_network; #- setup the DHCP server renamef($dhcpd_conf, "$dhcpd_conf.old"); output($dhcpd_conf, qq(subnet $lan_address.0 netmask 255.255.255.0 { # default gateway option routers $lan_address.1; option subnet-mask 255.255.255.0; option domain-name "homelan.org"; option domain-name-servers $lan_address.1; range dynamic-bootp $lan_address.16 $lan_address.253; default-lease-time 21600; max-lease-time 43200; } )); #- put the interface for the dhcp server in linuxconf config, for the /etc script of dhcpd substInFile { s/^DHCP.interface.*\n//; $_ .= "DHCP.interface $device\n" if eof } $conf_linuxconf; #- 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. substInFile { s/^ServerName[^:].*\n//; $_ .= "ServerName $lan_address.1\n" if eof; s/^BrowseAddress.*\n//; $_ .= "BrowseAddress $lan_address.255\n" if eof; s/^BrowseOrder.*\n//; $_ .= "BrowseOrder Deny,Allow\n" if eof; s/^BrowseDeny.*\n//; $_ .= "BrowseDeny All\n" if eof; s/^BrowseAllow.*\n//; $_ .= "BrowseAllow $lan_address.*\n" if eof; } $cups_conf; #- Modify the root location block in /etc/cups/cupsd.conf if (-f $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 (grep(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 $lan_address.*\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; } #- start the daemons start_daemons(); #- bye-bye message undef $wait_configuring; $::Wizard_no_previous = 1; $::Wizard_finished = 1; $in->ask_okcancel(_("Congratulations!"), _("Everything has been configured. You may now share Internet connection with other computers on your Local Area Network, using automatic network configuration (DHCP).")); log::l("[drakgw] Installation complete, exiting\n"); quit_global($in, 0); sub quit_global { my ($in, $exitcode) = @_; $in->exit($exitcode); goto begin } #------------------------------------------------- #- $Log$ #- Revision 1.29 2001/03/26 15:29:01 gc #- first attempt at pixelization of code (till's cups patches) #- #- Revision 1.28 2001/03/21 18:07:36 gc #- honour embedded mode #- #- Revision 1.27 2001/03/13 16:23:29 gc #- fix for bind #- #- Revision 1.26 2001/03/13 15:31:05 gc #- - fix destructive parts of pixelization #- - fix some own bugs #- #- Revision 1.25 2001/03/13 00:00:11 prigaux #- pixelization #- #- Revision 1.24 2001/03/12 18:26:16 gc #- - make it work as a wizard #- - make it work with iptables (kernel-2.4) #- #- Revision 1.23 2001/03/01 00:18:17 damien #- updated embedded mode #- #- Revision 1.22 2001/02/26 18:39:12 prigaux #- pixelization #- #- Revision 1.21 2001/02/08 10:11:37 damien #- implemented or updated embedded mode #- #- Revision 1.20 2001/02/08 07:00:41 damien #- added embedded and (ugly) wizard mode. #- #- Revision 1.19 2001/01/10 00:32:42 prigaux #- use standalone and standalone::pkgs_install #- #- Revision 1.18 2000/12/16 16:13:34 prigaux #- use ldetect-lst #- #- Revision 1.17 2000/11/13 15:48:33 gc #- Integrate Till's patches for better work with Cups. #- #- Revision 1.16 2000/10/10 15:31:50 gc #- make only one call to urpmi in order to install all the needed rpm's #-