#!/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(:system :file); use interactive; use log; use c; use netconnect; use detect_devices; local $_ = join '', @ARGV; /-h/ and die "usage: drakgw [--version --verbose]\n"; /-version/ and die 'version: $Id$ '."\n"; $::verbose = /-verbose/; $::direct = /-direct/; $::isStandalone = 1; my $in = vnew interactive('su'); my $sysconf_network = "/etc/sysconfig/network"; my $conf_linuxconf = "/etc/conf.linuxconf"; my $rc_firewall = "/etc/rc.d/rc.firewall.inet_sharing"; my $dhcpd_conf = "/etc/dhcpd.conf"; my $drakgw_setup = "/etc/sysconfig/inet_sharing"; sub start_daemons() { log::l("[drakgw] Starting daemons\n"); grep(/is running/, `/etc/rc.d/init.d/dhcpd status`) and ((system("/etc/rc.d/init.d/dhcpd stop") == 0) or die "Could not stop the dhcp server"); grep(/error: cannot connect/, `/etc/rc.d/init.d/named status 2>&1`) or ((system("/etc/rc.d/init.d/named stop") == 0) or die "Could not stop the named server"); (system("/etc/rc.d/init.d/network restart") == 0) or die "Could not restart the network"; (system("sh /etc/rc.d/rc.firewall") == 0) or die "Could not start the firewall script"; (system("/etc/rc.d/init.d/named start") == 0) or die "Could not start the caching nameserver"; (system("/sbin/chkconfig --level 345 named on") == 0) or die "Could not chkconfig named"; (system("/etc/rc.d/init.d/dhcpd start") == 0) or die "Could not start the dhcp server"; (system("/sbin/chkconfig --level 345 dhcpd on") == 0) or die "Could not chkconfig dhcpd"; local *DRAKGW_SETUP; open DRAKGW_SETUP, ">$drakgw_setup" or die "Can't open $drakgw_setup"; print DRAKGW_SETUP "INET_SHARING=enabled\n"; close DRAKGW_SETUP; } sub stop_daemons() { log::l("[drakgw] Stopping daemons\n"); grep(/is running/, `/etc/rc.d/init.d/dhcpd status`) and ((system("/etc/rc.d/init.d/dhcpd stop") == 0) or die "Could not stop the dhcp server"); grep(/Connection refused/, `/etc/rc.d/init.d/named status 2>&1`) or ((system("/etc/rc.d/init.d/named stop") == 0) or die "Could not stop the named server"); (system("/etc/rc.d/init.d/ipchains stop") == 0) or die "Could not stop ipchains"; (system("/sbin/chkconfig --level 345 named off") == 0) or die "Could not chkconfig named"; (system("/sbin/chkconfig --level 345 dhcpd off") == 0) or die "Could not chkconfig dhcpd"; local *DRAKGW_SETUP; open DRAKGW_SETUP, ">$drakgw_setup" or die "Can't open $drakgw_setup"; print DRAKGW_SETUP "INET_SHARING=disabled\n"; close DRAKGW_SETUP; } sub install_rpm($) { $in->suspend; system("urpmi --auto --best-output $_[0]"); $in->resume; } sub fatal_quit($) { log::l("[drakgw] FATAL: $_[0]\n"); (defined $wait_configuring) and (undef $wait_configuring); $in->ask_warn('', $_[0]); $in->exit(-1); } #- ********************************** #- * 0nd step: verify if we are already set up if (-f $drakgw_setup) { open DRAKGW_SETUP, "$drakgw_setup" or die "Can't open $drakgw_setup"; my @drakgw_setup_content = ; close DRAKGW_SETUP; if (grep(/enabled/, @drakgw_setup_content)) { 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.\n What would you like to do?"), [ _("disable"), _("reconfigure"), _("dismiss") ]); if ($r eq _("disable")) { stop_daemons(); -f "$dhcpd_conf.drakgwdisable" and (unlink("$dhcpd_conf.drakgwdisable") or die "Could not unlink $dhcpd_conf.drakgwdisable"); rename($dhcpd_conf, "$dhcpd_conf.drakgwdisable") or die "Could not rename $dhcpd_conf to $dhcpd_conf.drakgwdisable"; -f "$rc_firewall.drakgwdisable" and (unlink("$rc_firewall.drakgwdisable") or die "Could not unlink $rc_firewall.drakgwdisable"); rename($rc_firewall, "$rc_firewall.drakgwdisable") or die "Could not rename $rc_firewall to $rc_firewall.drakgwdisable"; log::l("[drakgw] Disabled\n"); $in->exit(0); } ($r eq _("dismiss")) and $in->exit(0); } elsif (grep(/disabled/, @drakgw_setup_content)) { 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.\n What would you like to do?"), [ _("enable"), _("reconfigure"), _("dismiss") ]); if ($r eq _("enable")) { -f $dhcpd_conf and rename($dhcpd_conf, "$dhcpd_conf.old"); rename("$dhcpd_conf.drakgwdisable", $dhcpd_conf) or die "Could not find configuration. Please reconfigure."; -f $rc_firewall and rename($rc_firewall, "$rc_firewall.old"); rename("$rc_firewall.drakgwdisable", $rc_firewall) or die "Could not find configuration. Please reconfigure."; start_daemons(); log::l("[drakgw] Enabled\n"); $in->exit(0); } ($r eq _("dismiss")) and $in->exit(0); } else { $in->ask_warn("Unrecognized config file", _("Config file content could not be interpreted.")); $in->exit(-1); } } #- ********************************** #- * 1st step: detect/setup $::direct or $in->ask_okcancel(_("Internet Connection Sharing"), _("Your computer can be configured to share its Internet connection.\n Note: you need a dedicated Network Adapter to set up a Local Area Network (LAN).\n Would you like to setup the Internet Connection Sharing?"), 1) or $in->exit(0); #my @pci_ethernet_cards; #require pci_probing::main; #($_->[0] =~ /NETWORK_ETHERNET/) and (push @pci_ethernet_cards, $_) foreach (pci_probing::main::probe('.')); #($#pci_ethernet_cards == -1) and $in->ask_warn('', _("No PCI network ethernet devices found!")) and $in->exit(0); # ## push @pci_ethernet_cards, [ "NETWORK_ETHERNET", "Fake ne2000", "ne2k" ]; my @configured_devices = map { /ifcfg-(\S+)/; $1 } `ls /etc/sysconfig/network-scripts/ifcfg*`; #my @active_devices = `/sbin/ifconfig | grep ^[a-z] | awk '{print \$1}'`; chop @active_devices; my %aliased_devices; (/^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\n"); my @all_cards_getnet = detect_devices::getNet(); my @all_cards; foreach my $card (@all_cards_getnet) { log::l("[drakgw] Have network card: $card\n"); next if ($card eq $card_netconnect); push @all_cards, exists $aliased_devices{$card} ? "Interface $card (using module $aliased_devices{$card})" : "Interface $card"; } log::l("[drakgw] Available network cards: ".join(" ; ", @all_cards)."\n"); # print "pci_detection: "; print ">".$_->[2]."< " foreach (@pci_ethernet_cards); # print "\nconfigured: "; print ">".$_."< " foreach (@configured_devices); # print "\nactive: "; print ">".$_."< " foreach (@active_devices); # print "\naliased: "; print ">".$_." => ".$aliased_devices{$_}."< " foreach (keys %aliased_devices); # print "\n"; # print "\nall_cards: "; print ">".$_."< " foreach (@all_cards); # #foreach $pci_card (@pci_ethernet_cards) #{ # my $this_card = $pci_card->[1]; # foreach $aliased_dev (keys %aliased_devices) # { # if ($pci_card->[2] eq $aliased_devices{$aliased_dev}) # { # $this_card .= ", hardware-configured"; # grep(/$aliased_dev/, @configured_devices) and $this_card .= ", software-configured"; # grep(/$aliased_dev/, @active_devices) and $this_card .= ", active"; # } # } # push @all_cards, $this_card; #} #- setup the network interface we shall use my $interface; if ($#all_cards == -1) { $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.")); $in->exit(0); } elsif ($#all_cards == 0) { $interface = $all_cards[0]; $::verbose and ($in->ask_okcancel(_("Network interface"), _("There is only one configured network adapter on your system:\n\n$interface\n\nWould you like to setup your Local Area Network with that adapter?"), 1) or $in->exit(0)); } else { $interface = $in->ask_from_list(_("Choose the network interface"), _("Please choose what network adapter will be connected to your Local Area Network."), \@all_cards, ); defined $interface or $in->exit(0); } $interface =~ /(eth[0-9]+)/ or die("Internal error"); my $device = $1; log::l("[drakgw] Choosing network card: $device\n"); grep(/$device/, @configured_devices) and ($in->ask_okcancel('', _("Warning, the network adapter is already configured.\nWould you like to reconfigure?")) or $in->exit(0)); #- setup the address for the LAN my $full_lan_address = "192.168.0.0"; #$::expert and ($full_lan_address = $in->ask_from_entry(_("Local Area Network specification"), # _("You may now decide which class C network to use.\n"), # _("Network:"), $full_lan_address, # ) or $in->exit(0)); ($full_lan_address =~ /^([0-9]+\.[0-9]+\.[0-9]+)\.0$/) or die "Invalid network.\n"; my $lan_address = $1; #- test for potential conflict with other networks foreach (@configured_devices) { if ($_ ne $device) { local *IFCFG; my $ifcfg = "/etc/sysconfig/network-scripts/ifcfg-$_"; open IFCFG, "$ifcfg" or die "Can't open $ifcfg"; my @ifcfg_content = ; grep(/$lan_address/, @ifcfg_content) and $in->ask_warn('', _("Potential LAN address conflict found in current config of $_!\n")) and $in->exit(0); close IFCFG; } } #- test for potential conflict with previous firewall config my @chain_rules; (-f "/etc/sysconfig/ipchains" or ((-x "/sbin/ipchains") and (@chain_rules = `/sbin/ipchains -L`) and ($#chain_rules > 2))) and ($in->ask_okcancel(_("Firewalling configuration detected!"), _("Warning! An existing firewalling configuration has been detected. You may need some manual fix after installation. Proceed?"), 1) or $in->exit(0)); #- ask for confirmation # #$in->ask_okcancel(_("Internet Connection Sharing - setup"), # _("The local network is about to be configured.\n") . # "You will then be able to connect other computers to this network, with automatic ". # "DHCP configuration."), 1) or $in->exit(0); #- ********************************** #- * 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"; -f "$network_scripts/ifcfg-$device" and rename("$network_scripts/ifcfg-$device", "$network_scripts/old.ifcfg-$device"); my $ifcfg = "$network_scripts/ifcfg-$device"; local *IFCFG; open IFCFG, ">$ifcfg" or die "Can't open $ifcfg"; print IFCFG <; close RCFIREWALL; grep(/\/etc\/rc\.d\/rc\.firewall\.inet_sharing/, @rcfirewall_content) or push @rcfirewall_content, "# Added by drakgw\n[ -x /etc/rc.d/rc.firewall.inet_sharing ] && /etc/rc.d/rc.firewall.inet_sharing\n"; open RCFIREWALL, ">/etc/rc.d/rc.firewall" or die "Can't open /etc/rc.d/rc.firewall"; print RCFIREWALL @rcfirewall_content; close RCFIREWALL; } else { local *RCFIREWALL; open RCFIREWALL, ">/etc/rc.d/rc.firewall" or die "Can't open /etc/rc.d/rc.firewall"; print RCFIREWALL <$rc_firewall" or die "Can't open $rc_firewall"; print RCFIREWALL < /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 EOF close RCFIREWALL; chmod 0700, $rc_firewall; #- be sure that FORWARD_IPV4 is enabled in /etc/sysconfig/network open SYSCONF_NETWORK, "$sysconf_network" or die "Can't open $sysconf_network"; my @sysconf_network_content = ; close SYSCONF_NETWORK; ($_ =~ /^FORWARD_IPV4=/ and $_="FORWARD_IPV4=true\n") foreach @sysconf_network_content; grep(/^FORWARD_IPV4=/, @sysconf_network_content) or push @sysconf_network_content, "FORWARD_IPV4=true\n"; open SYSCONF_NETWORK, ">$sysconf_network" or die "Can't open $sysconf_network"; print SYSCONF_NETWORK @sysconf_network_content; close SYSCONF_NETWORK; #- install and setup the DHCP server $f = "/usr/sbin/dhcpd"; -e $f or install_rpm("dhcp"); -e $f or fatal_quit(_("Could not install dhcp RPM with urpmi.")); -f $dhcpd_conf and rename($dhcpd_conf, "$dhcpd_conf.old"); local *DHCPDCONF; open DHCPDCONF, ">$dhcpd_conf" or die "Can't open $dhcpd_conf"; print DHCPDCONF <; close CONF_LINUXCONF; ($_ =~ /^DHCP.interface/ and $_="DHCP.interface $device\n") foreach @conf_linuxconf_content; grep(/DHCP.interface/, @conf_linuxconf_content) or push @conf_linuxconf_content, "DHCP.interface $device\n"; open CONF_LINUXCONF, ">$conf_linuxconf" or die "Can't open $conf_linuxconf"; print CONF_LINUXCONF @conf_linuxconf_content; close CONF_LINUXCONF; #- install the BIND and caching nameserver stuff $f = "/usr/sbin/named"; -e $f or install_rpm("bind"); -e $f or fatal_quit(_("Could not install bind RPM with urpmi.")); $f = "/var/named/named.local"; -e $f or install_rpm("caching-nameserver"); -e $f or fatal_quit(_("Could not install caching-nameserver RPM with urpmi.")); #- start the daemons start_daemons(); #- bye-bye message undef $wait_configuring; $in->ask_warn(_("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"); $in->exit(0);