summaryrefslogtreecommitdiffstats
path: root/perl-install/network.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/network.pm')
-rw-r--r--perl-install/network.pm414
1 files changed, 360 insertions, 54 deletions
diff --git a/perl-install/network.pm b/perl-install/network.pm
index 29edb4ff3..5e687c857 100644
--- a/perl-install/network.pm
+++ b/perl-install/network.pm
@@ -1,21 +1,41 @@
-package network;
+package network; # $Id$
use diagnostics;
use strict;
+#-######################################################################################
+#- misc imports
+#-######################################################################################
use Socket;
-use common qw(:common :file :system);
+use common qw(:common :file :system :functional);
use detect_devices;
-use modules;
+use run_program;
+use any;
use log;
-1;
-
-
+#-######################################################################################
+#- Functions
+#-######################################################################################
sub read_conf {
my ($file) = @_;
my %netc = getVarsFromSh($file);
+ $netc{dnsServer} = delete $netc{NS0};
+ $netc{dnsServer2} = delete $netc{NS1};
+ $netc{dnsServer3} = delete $netc{NS2};
+ \%netc;
+}
+
+sub read_resolv_conf {
+ my ($file) = @_;
+ my @l = qw(dnsServer dnsServer2 dnsServer3);
+ my %netc;
+
+ local *F; open F, $file or die "cannot open $file: $!";
+ local $_;
+ while (<F>) {
+ /^\s*nameserver\s+(\S+)/ and $netc{shift @l} = $1;
+ }
\%netc;
}
@@ -29,31 +49,95 @@ sub read_interface_conf {
\%intf;
}
+sub up_it {
+ my ($prefix, $intfs) = @_;
+ $_->{isUp} and return foreach values %$intfs;
+ my $f = "/etc/resolv.conf"; symlink "$prefix/$f", $f;
+ run_program::rooted($prefix, "/etc/rc.d/init.d/network", "start");
+ $_->{isUp} = 1 foreach values %$intfs;
+}
+sub down_it {
+ my ($prefix, $intfs) = @_;
+ run_program::rooted($prefix, "/etc/rc.d/init.d/network", "stop");
+ $_->{isUp} = 1 foreach values %$intfs;
+}
+
sub write_conf {
my ($file, $netc) = @_;
add2hash($netc, {
- NETWORKING => "yes",
- FORWARD_IPV4 => "false",
+ NETWORKING => "yes",
+ FORWARD_IPV4 => "false",
HOSTNAME => "localhost.localdomain",
- DOMAINNAME => "localdomain",
- });
-
- setVarsInSh($file, $netc, qw(NETWORKING FORWARD_IPV4 HOSTNAME DOMAINNAME GATEWAY GATEWAYDEV));
+ });
+ add2hash($netc, { DOMAINNAME => $netc->{HOSTNAME} =~ /\.(.*)/ });
+
+ setVarsInSh($file, $netc, qw(NETWORKING FORWARD_IPV4 DHCP_HOSTNAME HOSTNAME DOMAINNAME GATEWAY GATEWAYDEV NISDOMAIN));
+}
+
+sub write_resolv_conf {
+ my ($file, $netc) = @_;
+
+ #- get the list of used dns.
+ my %used_dns; @used_dns{$netc->{dnsServer}, $netc->{dnsServer2}, $netc->{dnsServer3}} = (1, 2, 3);
+
+ unless ($netc->{DOMAINNAME} || $netc->{DOMAINNAME2} || keys %used_dns > 0) {
+ unlink($file);
+ log::l("neither domain name nor dns server are configured");
+ return 0;
+ }
+
+ my (%search, %dns, @unknown);
+ local *F; open F, $file;
+ local $_;
+ while (<F>) {
+ /^[#\s]*search\s+(.*?)\s*$/ and $search{$1} = $., next;
+ /^[#\s]*nameserver\s+(.*?)\s*$/ and $dns{$1} = $., next;
+ /^.*# ppp temp entry\s*$/ and next;
+ /^[#\s]*(\S.*?)\s*$/ and push @unknown, $1;
+ }
+
+ close F; open F, ">$file" or die "cannot write $file: $!";
+ print F "# search $_\n" foreach grep { $_ ne "$netc->{DOMAINNAME} $netc->{DOMAINNAME2}" } sort { $search{$a} <=> $search{$b} } keys %search;
+ print F "search $netc->{DOMAINNAME} $netc->{DOMAINNAME2}\n\n" if ($netc->{DOMAINNAME} || $netc->{DOMAINNAME2});
+ print F "# nameserver $_\n" foreach grep { ! exists $used_dns{$_} } sort { $dns{$a} <=> $dns{$b} } keys %dns;
+ print F "nameserver $_\n" foreach sort { $used_dns{$a} <=> $used_dns{$b} } grep { $_ } keys %used_dns;
+ print F "\n";
+ print F "# $_\n" foreach @unknown;
+ print F "\n";
+ print F "# ppp temp entry\n";
+
+ #-res_init(); # reinit the resolver so DNS changes take affect
+ 1;
+}
+
+sub write_interface_conf {
+ my ($file, $intf) = @_;
+
+ my @ip = split '\.', $intf->{IPADDR};
+ my @mask = split '\.', $intf->{NETMASK};
+ add2hash($intf, {
+ BROADCAST => join('.', mapn { int $_[0] | ~int $_[1] & 255 } \@ip, \@mask),
+ NETWORK => join('.', mapn { int $_[0] & $_[1] } \@ip, \@mask),
+ ONBOOT => bool2yesno(!member($intf->{DEVICE}, map { $_->{device} } detect_devices::probeall())),
+ });
+ setVarsInSh($file, $intf, qw(DEVICE BOOTPROTO IPADDR NETMASK NETWORK BROADCAST ONBOOT));
}
sub add2hosts {
- my ($file, $ip, $hostname) = @_;
- my %l = ($ip => $hostname);
+ my ($file, $hostname, @ips) = @_;
+ my %l;
+ $l{$_} = $hostname foreach @ips;
local *F;
if (-e $file) {
open F, $file or die "cannot open $file: $!";
- /\s*(\S+)(.*)/ and $l{$1} = $2 foreach <F>;
+ /\s*(\S+)(.*)/ and $l{$1} ||= $2 foreach <F>;
}
log::l("writing host information to $file");
open F, ">$file" or die "cannot write $file: $!";
while (my ($ip, $v) = each %l) {
+ $ip or next;
print F "$ip";
if ($v =~ /^\s/) {
print F $v;
@@ -65,65 +149,287 @@ sub add2hosts {
}
}
-sub write_resolv_conf {
- my ($file, $netc) = @_;
+# The interface/gateway needs to be configured before this will work!
+sub guessHostname {
+ my ($prefix, $netc, $intf) = @_;
- # We always write these, even if they were autoconfigured. Otherwise, the reverse name lookup in the install doesn't work.
- unless ($netc->{DOMAINNAME} || $netc->{dnsServers}) {
- unlink($file);
- log::l("neither domain name nor dns server are configured");
- return 0;
- }
- my @l = cat_($file);
+ $intf->{isUp} && dnsServers($netc) or return 0;
+ $netc->{HOSTNAME} && $netc->{DOMAINNAME} and return 1;
- local *F;
- open F, "> $file" or die "cannot write $file: $!";
- print F "search $netc->{DOMAINNAME}\n" if $netc->{DOMAINNAME};
- print F "nameserver $_\n" foreach @{$netc->{dnsServers}};
- print F "#$_" foreach @l;
+ write_resolv_conf("$prefix/etc/resolv.conf", $netc);
- #res_init(); # reinit the resolver so DNS changes take affect
+ my $name = gethostbyaddr(Socket::inet_aton($intf->{IPADDR}), AF_INET) or log::l("reverse name lookup failed"), return 0;
+
+ log::l("reverse name lookup worked");
+
+ add2hash($netc, { HOSTNAME => $name });
1;
}
-sub write_interface_conf {
- my ($file, $intf) = @_;
+sub addDefaultRoute {
+ my ($netc) = @_;
+ c::addDefaultRoute($netc->{GATEWAY}) if $netc->{GATEWAY};
+}
- add2hash($intf, { ONBOOT => "yes" });
- setVarsInSh($file, $intf, qw(DEVICE BOOTPROTO IPADDR NETMASK NETWORK BROADCAST ONBOOT));
+sub sethostname {
+ my ($netc) = @_;
+ syscall_('sethostname', $netc->{HOSTNAME}, length $netc->{HOSTNAME}) or log::l("sethostname failed: $!");
}
+sub resolv($) {
+ my ($name) = @_;
+ is_ip($name) and return $name;
+ my $a = join(".", unpack "C4", (gethostbyname $name)[4]);
+ #-log::l("resolved $name in $a");
+ $a;
+}
-# The interface/gateway needs to be configured before this will work!
-sub guessHostname {
- my ($prefix, $netc, $intf) = @_;
+sub dnsServers {
+ my ($netc) = @_;
+ my %used_dns; @used_dns{$netc->{dnsServer}, $netc->{dnsServer2}, $netc->{dnsServer3}} = (1, 2, 3);
+ sort { $used_dns{$a} <=> $used_dns{$b} } grep { $_ } keys %used_dns;
+}
- $intf->{isUp} && $netc->{dnsServers} or return 0;
- $netc->{HOSTNAME} && $netc->{DOMAINNAME} and return 1;
+sub findIntf {
+ my ($intf, $device) = @_;
+ $intf->{$device} ||= { DEVICE => $device };
+}
+#PAD \s* a la fin
+my $ip_regexp = qr/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
+sub is_ip {
+ my ($ip) = @_;
+ return 0 unless $ip =~ $ip_regexp;
+ my @fields = ($1, $2, $3, $4);
+ foreach (@fields) {
+ return 0 if $_ < 0 || $_ > 255;
+ }
+ return 1;
+}
- write_resolv_conf("$prefix/etc/resolv.conf", $netc);
+sub netmask {
+ my ($ip) = @_;
+ return "255.255.255.0" unless is_ip($ip);
+ $ip =~ $ip_regexp;
+ if ($1 >= 1 && $1 < 127) {
+ return "255.0.0.0"; #-1.0.0.0 to 127.0.0.0
+ } elsif ($1 >= 128 && $1 <= 191 ){
+ return "255.255.0.0"; #-128.0.0.0 to 191.255.0.0
+ } elsif ($1 >= 192 && $1 <= 223) {
+ return "255.255.255.0";
+ } else {
+ return "255.255.255.255"; #-experimental classes
+ }
+}
-# winStatus(40, 3, _("Hostname"), _("Determining host name and domain..."));
- my $name = gethostbyaddr(Socket::inet_aton($intf->{IPADDR}), AF_INET) or log::l("reverse name lookup failed"), return 0;
+sub masked_ip {
+ my ($ip) = @_;
+ return "" unless is_ip($ip);
+ my @mask = netmask($ip) =~ $ip_regexp;
+ my @ip = $ip =~ $ip_regexp;
+ for (my $i = 0; $i < @ip; $i++) {
+ $ip[$i] &= int $mask[$i];
+ }
+ join(".", @ip);
+}
- log::l("reverse name lookup worked");
+sub dns {
+ my ($ip) = @_;
+ my $mask = masked_ip($ip);
+ my @masked = masked_ip($ip) =~ $ip_regexp;
+ $masked[3] = 2;
+ join (".", @masked);
- add2hash($netc, { HOSTNAME => $name, DOMAINNAME => $name =~ /\.(.*)/ });
- 1;
}
+sub gateway {
+ my ($ip) = @_;
+ my @masked = masked_ip($ip) =~ $ip_regexp;
+ $masked[3] = 1;
+ join (".", @masked);
-sub addDefaultRoute {
- my ($netc) = @_;
- c::addDefaultRoute($netc->{gateway}) if $netc->{gateway} || !$::testing;
}
-sub getAvailableNetDevice {
- my $device = detect_devices::getNet();
+sub configureNetwork {
+ my ($prefix, $netc, $in, $intf, $first_time) = @_;
+ local $_;
+ any::setup_thiskind($in, 'net', !$::expert, 1);
+ my @l = detect_devices::getNet() or die _("no network card found");
+
+ my $last; foreach ($::beginner ? $l[0] : @l) {
+ my $intf2 = findIntf($intf ||= {}, $_);
+ add2hash($intf2, $last);
+ add2hash($intf2, { NETMASK => '255.255.255.0' });
+ configureNetworkIntf($in, $intf2, $netc->{NET_DEVICE}, 0) or last;
+
+ $netc ||= {};
+ $last = $intf2;
+ }
+ #- {
+ #- my $wait = $o->wait_message(_("Hostname"), _("Determining host name and domain..."));
+ #- network::guessHostname($o->{prefix}, $o->{netc}, $o->{intf});
+ #- }
+ $last or return;
+ if ($last->{BOOTPROTO} =~ /^(dhcp|bootp)$/) {
+ $netc->{minus_one} = 1;
+ my $dhcp_hostname = $netc->{HOSTNAME};
+ $::isInstall and $in->set_help('configureNetworkHostDHCP');
+ $in->ask_from_entries_ref(_("Configuring network"),
+_("Please enter your host name if you know it.
+Some DHCP servers require the hostname to work.
+Your host name should be a fully-qualified host name,
+such as ``mybox.mylab.myco.com''."),
+ [_("Host name")], [ \$netc->{HOSTNAME} ]);
+ $netc->{HOSTNAME} ne $dhcp_hostname and $netc->{DHCP_HOSTNAME} = $netc->{HOSTNAME};
+ } else {
+ configureNetworkNet($in, $netc, $last ||= {}, @l);
+ if ( $netc->{GATEWAY} ) {
+ unlink "$prefix/etc/sysconfig/network-scripts/net_cnx_up";
+ unlink "$prefix/etc/sysconfig/network-scripts/net_cnx_down";
+ undef $netc->{NET_DEVICE};
+ }
+ }
+ miscellaneousNetwork($in);
+}
+
- unless ($device) {
- modules::load_thiskind('net') or return;
- $device = detect_devices::getNet();
+sub configureNetworkIntf {
+ my ($in, $intf, $net_device, $skip) = @_;
+ my $text;
+ if ($net_device eq $intf->{DEVICE}) {
+ $skip and return 1;
+ $text = _("WARNING: This device has been previously configured to connect to the Internet.
+Simply press OK to keep this device configured.
+Modifying the fields below will override this configuration.");
+ }
+ else {
+ $text = _("Please enter the IP configuration for this machine.
+Each item should be entered as an IP address in dotted-decimal
+notation (for example, 1.2.3.4).");
}
- $device;
+ my $pump = $intf->{BOOTPROTO} =~ /^(dhcp|bootp)$/;
+ delete $intf->{NETWORK};
+ delete $intf->{BROADCAST};
+ my @fields = qw(IPADDR NETMASK);
+ $::isStandalone or $in->set_help('configureNetworkIP');
+ $in->ask_from_entries_ref(_("Configuring network device %s", $intf->{DEVICE}),
+ ($::isStandalone ? '' : _("Configuring network device %s", $intf->{DEVICE}) . "\n\n") .
+ $text,
+ [ _("IP address"), _("Netmask"), _("Automatic IP") ],
+ [ \$intf->{IPADDR}, \$intf->{NETMASK}, { val => \$pump, type => "bool", text => _("(bootp/dhcp)") } ],
+ complete => sub {
+ $intf->{BOOTPROTO} = $pump ? "dhcp" : "static";
+ return 0 if $pump;
+ for (my $i = 0; $i < @fields; $i++) {
+ unless (is_ip($intf->{$fields[$i]})) {
+ $in->ask_warn('', _("IP address should be in format 1.2.3.4"));
+ return (1,$i);
+ }
+ return 0;
+ }
+ },
+ focus_out => sub {
+ $intf->{NETMASK} ||= netmask($intf->{IPADDR}) unless $_[0]
+ }
+ );
+}
+
+sub configureNetworkNet {
+ my ($in, $netc, $intf, @devices) = @_;
+
+ $netc->{dnsServer} ||= dns($intf->{IPADDR});
+ $netc->{GATEWAY} ||= gateway($intf->{IPADDR});
+
+ $::isInstall and $in->set_help('configureNetworkHost');
+ $in->ask_from_entries_refH(_("Configuring network"),
+_("Please enter your host name.
+Your host name should be a fully-qualified host name,
+such as ``mybox.mylab.myco.com''.
+You may also enter the IP address of the gateway if you have one"),
+ [ _("Host name") => \$netc->{HOSTNAME},
+ _("DNS server") => \$netc->{dnsServer},
+ _("Gateway") => \$netc->{GATEWAY},
+ $::expert ? (_("Gateway device") => {val => \$netc->{GATEWAYDEV}, list => \@devices }) : (),
+ ],
+ ) or return;
+}
+
+sub miscellaneousNetwork {
+ my ($in, $clicked) = @_;
+ my $u = $::o->{miscellaneous} ||= {};
+ $::isInstall and $in->set_help('configureNetworkProxy');
+ !$::beginner || $clicked and $in->ask_from_entries_ref('',
+ _("Proxies configuration"),
+ [ _("HTTP proxy"),
+ _("FTP proxy"),
+ ],
+ [ \$u->{http_proxy},
+ \$u->{ftp_proxy},
+ ],
+ complete => sub {
+ $u->{http_proxy} =~ m,^($|http://), or $in->ask_warn('', _("Proxy should be http://...")), return 1,0;
+ $u->{ftp_proxy} =~ m,^($|ftp://), or $in->ask_warn('', _("Proxy should be ftp://...")), return 1,1;
+ 0;
+ }
+ ) || return;
}
+sub read_all_conf {
+ my ($prefix, $netc, $intf) = @_;
+ $netc ||= {}; $intf ||= {};
+ add2hash($netc, read_conf("$prefix/etc/sysconfig/network")) if -r "$prefix/etc/sysconfig/network";
+ add2hash($netc, read_resolv_conf("$prefix/etc/resolv.conf")) if -r "$prefix/etc/resolv.conf";
+ foreach (all("$prefix/etc/sysconfig/network-scripts")) {
+ if (/ifcfg-(\w+)/ && $1 ne 'lo' && $1 !~ /ppp/) {
+ my $intf = findIntf($intf, $1);
+ add2hash($intf, { getVarsFromSh("$prefix/etc/sysconfig/network-scripts/$_") });
+ }
+ }
+}
+
+#- configureNetwork2 : configure the network interfaces.
+#- input
+#- $prefix
+#- $netc
+#- $intf
+#- $install : a function that takes a list of package and install them : ex sub { system("urpmi --auto --best-output " . join(' ', @_)); }
+#- $netc input
+#- NETWORKING : networking flag : string : "yes" by default
+#- FORWARD_IPV4 : forward IP flag : string : "false" by default
+#- HOSTNAME : hostname : string : "localhost.localdomain" by default
+#- DOMAINNAME : domainname : string : $netc->{HOSTNAME} =~ /\.(.*)/ by default
+#- DOMAINNAME2 : well it's another domainname : have to look further why we used 2
+#- The following are facultatives
+#- DHCP_HOSTNAME : If you have a dhcp and want to set the hostname
+#- GATEWAY : gateway
+#- GATEWAYDEV : gateway interface
+#- NISDOMAIN : nis domain
+#- $netc->{dnsServer} : dns server 1
+#- $netc->{dnsServer2} : dns server 2
+#- $netc->{dnsServer3} : dns server 3 : note that we uses the dns1 for the LAN, and the 2 others for the internet conx
+#- $intf input: for each $device (for example ethx)
+#- $intf->{$device}{IPADDR} : IP address
+#- $intf->{$device}{NETMASK} : netmask
+#- $intf->{$device}{DEVICE} : DEVICE = $device
+#- $intf->{$device}{BOOTPROTO} : boot prototype : "bootp" or "dhcp" or "pump" or ...
+sub configureNetwork2 {
+ my ($prefix, $netc, $intf, $install) = @_;
+ my $etc = "$prefix/etc";
+
+ write_conf("$etc/sysconfig/network", $netc);
+ write_resolv_conf("$etc/resolv.conf", $netc);
+ write_interface_conf("$etc/sysconfig/network-scripts/ifcfg-$_->{DEVICE}", $_) foreach values %$intf;
+ add2hosts("$etc/hosts", $netc->{HOSTNAME}, map { $_->{IPADDR} } values %$intf);
+ sethostname($netc) unless $::testing;
+ addDefaultRoute($netc) unless $::testing;
+
+ grep { $_->{BOOTPROTO} =~ /^(dhcp)$/ } values %$intf and $install && $install->('dhcpcd');
+ grep { $_->{BOOTPROTO} =~ /^(pump|bootp)$/ } values %$intf and $install && $install->('pump');
+ #-res_init(); #- reinit the resolver so DNS changes take affect
+
+ any::miscellaneousNetwork($prefix);
+}
+
+
+#-######################################################################################
+#- Wonderful perl :(
+#-######################################################################################
+1;