summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorNicolas Lécureuil <nlecureuil@mandriva.com>2011-08-30 13:16:42 +0000
committerNicolas Lécureuil <nlecureuil@mandriva.com>2011-08-30 13:16:42 +0000
commitc590a4a7c162d1a81dbf02ca2e174384af0385bb (patch)
tree7e1279550b8e48add99b7b41281d27d249d279f3 /lib
parent39d2ee13572a6dc634c0c454dfc43e0297483279 (diff)
downloaddrakx-net-c590a4a7c162d1a81dbf02ca2e174384af0385bb.tar
drakx-net-c590a4a7c162d1a81dbf02ca2e174384af0385bb.tar.gz
drakx-net-c590a4a7c162d1a81dbf02ca2e174384af0385bb.tar.bz2
drakx-net-c590a4a7c162d1a81dbf02ca2e174384af0385bb.tar.xz
drakx-net-c590a4a7c162d1a81dbf02ca2e174384af0385bb.zip
Create 2010.1 branch for drakx-net
Diffstat (limited to 'lib')
-rw-r--r--lib/network/.perl_checker1
-rw-r--r--lib/network/adsl.pm52
-rw-r--r--lib/network/connection.pm350
-rw-r--r--lib/network/connection/.perl_checker1
-rw-r--r--lib/network/connection/cable.pm74
-rw-r--r--lib/network/connection/cellular.pm99
-rw-r--r--lib/network/connection/cellular_bluetooth.pm103
-rw-r--r--lib/network/connection/cellular_card.pm278
-rw-r--r--lib/network/connection/dvb.pm70
-rw-r--r--lib/network/connection/ethernet.pm552
-rw-r--r--lib/network/connection/isdn.pm230
-rw-r--r--lib/network/connection/isdn/consts.pm460
-rw-r--r--lib/network/connection/pots.pm133
-rw-r--r--lib/network/connection/ppp.pm150
-rw-r--r--lib/network/connection/providers/cellular.pm183
-rw-r--r--lib/network/connection/providers/cellular_extra.pm2284
-rw-r--r--lib/network/connection/providers/xdsl.pm1352
-rw-r--r--lib/network/connection/wireless.pm1132
-rw-r--r--lib/network/connection/xdsl.pm412
-rw-r--r--lib/network/connection_manager.pm506
-rw-r--r--lib/network/dhcpd.pm50
-rw-r--r--lib/network/drakconnect.pm26
-rw-r--r--lib/network/drakconnect/.perl_checker1
-rw-r--r--lib/network/drakconnect/delete.pm68
-rw-r--r--lib/network/drakconnect/edit.pm525
-rw-r--r--lib/network/drakconnect/global.pm107
-rw-r--r--lib/network/drakfirewall.pm372
-rwxr-xr-xlib/network/drakroam.pm136
-rw-r--r--lib/network/drakvpn.pm120
-rw-r--r--lib/network/ifw.pm160
-rw-r--r--lib/network/invictus.pm30
-rw-r--r--lib/network/ipsec.pm619
-rw-r--r--lib/network/modem.pm218
-rw-r--r--lib/network/monitor.pm136
-rw-r--r--lib/network/ndiswrapper.pm160
-rw-r--r--lib/network/net_applet/ifw.pm227
-rwxr-xr-xlib/network/netcenter.pm215
-rw-r--r--lib/network/netconnect.pm867
-rw-r--r--lib/network/network.pm832
-rw-r--r--lib/network/nfs.pm99
-rw-r--r--lib/network/pxe.pm286
-rw-r--r--lib/network/rfswitch.pm38
-rw-r--r--lib/network/shorewall.pm246
-rw-r--r--lib/network/signal_strength.pm14
-rw-r--r--lib/network/squid.pm74
-rw-r--r--lib/network/test.pm161
-rw-r--r--lib/network/thirdparty.pm387
-rw-r--r--lib/network/tools.pm278
-rw-r--r--lib/network/vpn.pm191
-rw-r--r--lib/network/vpn/openvpn.pm409
-rw-r--r--lib/network/vpn/vpnc.pm74
51 files changed, 15548 insertions, 0 deletions
diff --git a/lib/network/.perl_checker b/lib/network/.perl_checker
new file mode 100644
index 0000000..2326e2f
--- /dev/null
+++ b/lib/network/.perl_checker
@@ -0,0 +1 @@
+Basedir ../..
diff --git a/lib/network/adsl.pm b/lib/network/adsl.pm
new file mode 100644
index 0000000..c012219
--- /dev/null
+++ b/lib/network/adsl.pm
@@ -0,0 +1,52 @@
+package network::adsl; # $Id$
+
+use common;
+use run_program;
+use network::tools;
+use modules;
+
+sub adsl_probe_info {
+ my ($net) = @_;
+ my $pppoe_file = "$::prefix/etc/ppp/pppoe.conf";
+ my $login;
+ foreach (qw(/etc/ppp/peers/ppp0 /etc/ppp/options /etc/ppp/options.adsl)) {
+ ($login) = map { if_(/^user\s+"([^"]+)"/, $1) } cat_("$::prefix/$_") if !$login && -r "$::prefix/$_";
+ }
+ my %pppoe_conf = -f $pppoe_file && getVarsFromSh($pppoe_file);
+ $login = $pppoe_conf{USER} if !$login || $net->{adsl}{method} eq 'pppoe';
+ my $passwd = network::tools::passwd_by_login($login);
+ if (!$net->{adsl}{vpi} && !$net->{adsl}{vci}) {
+ foreach (cat_("$::prefix/etc/ppp/peers/ppp0")) {
+ if (/^.*-vpi\s+(\d+)\s+-vci\s+(\d+)/ || /^plugin pppoatm.so (\d+)\.(\d+)$/) {
+ ($net->{adsl}{vpi}, $net->{adsl}{vci}) = ($1, $2);
+ last;
+ }
+ }
+ }
+ $pppoe_conf{DNS1} ||= '';
+ $pppoe_conf{DNS2} ||= '';
+ add2hash($net->{resolv}, { dnsServer2 => $pppoe_conf{DNS1}, dnsServer3 => $pppoe_conf{DNS2}, DOMAINNAME2 => '' });
+ add2hash($net->{adsl}, { login => $login, passwd => $passwd });
+}
+
+sub adsl_conf_backend {
+ my ($in, $net) = @_;
+
+ require network::connection::xdsl;
+ my $xdsl = network::connection::xdsl->new(
+ $net->{adsl}{method} eq "capi" ?
+ $net->{adsl}{capi_card} :
+ { driver => $net->{adsl}{driver}, ethernet_device => $net->{adsl}{ethernet_device} });
+ $xdsl->{protocol} = $net->{adsl}{method};
+ $xdsl->{access}{login} = $net->{adsl}{login};
+ $xdsl->{access}{password} = $net->{adsl}{passwd};
+ $xdsl->{access}{vpi} = $net->{adsl}{vpi};
+ $xdsl->{access}{vci} = $net->{adsl}{vci};
+
+ $xdsl->install_packages($in);
+ $xdsl->unload_connection;
+ $xdsl->write_settings($net);
+ $xdsl->prepare_connection;
+}
+
+1;
diff --git a/lib/network/connection.pm b/lib/network/connection.pm
new file mode 100644
index 0000000..837ab97
--- /dev/null
+++ b/lib/network/connection.pm
@@ -0,0 +1,350 @@
+package network::connection;
+
+use common;
+use network::vpn;
+
+sub get_types {
+ sort { $a->get_metric <=> $b->get_metric } grep { $_->can('get_devices') } common::load_modules_from_base(__PACKAGE__);
+}
+
+=item get_type_name()
+
+Get the connection type name, unstranslated
+
+=cut
+
+sub get_type_name() { N("Unknown connection type") }
+sub get_type_description {
+ my ($class) = @_;
+ $class->get_type_name;
+}
+
+=item get_type_icon()
+
+Get the connection type icon path
+
+=cut
+
+sub get_type_icon {
+ my ($self, $o_size) = @_;
+ my $size = $o_size || 24;
+ my $icon = eval { $self->_get_type_icon . '-' . $size };
+ $icon || '/usr/share/mcc/themes/default/drakconnect-mdk';
+}
+
+=item get_devices(%options)
+
+Get the devices supported by this connection type
+Options:
+- automatic_only (no device requiring manual configuration should be returned)
+- fast_only (no slow detection should be performed)
+
+=cut
+
+=item get_connections(%options)
+
+List connections that can be configured by the class
+Options: see get_devices()
+
+=cut
+
+sub get_connections {
+ my ($class, %options) = @_;
+ map { $class->new($_) } $class->get_devices(%options);
+}
+
+=item find_ifcfg_type($ifcfg)
+
+Returns the class matching the connection type of the ifcfg hash
+
+=cut
+
+sub find_ifcfg_type {
+ my ($_class, $ifcfg) = @_;
+ find { $_->can('handles_ifcfg') && $_->handles_ifcfg($ifcfg) } sort { $b->get_metric <=> $a->get_metric } get_types();
+}
+
+sub new {
+ my ($class, $device) = @_;
+ bless {
+ device => $device,
+ settings => {},
+ networks => {},
+ }, $class;
+}
+
+sub get_description {
+ my ($self) = @_;
+ my $description = $self->{device}{description};
+ $description =~ s/\|/ /g;
+ $description;
+}
+
+sub get_label {
+ my ($self) = @_;
+ my $intf = $self->get_interface;
+ my $descr = $self->get_description;
+ $intf ? sprintf("%s (%s)", $descr, $intf) : $descr;
+}
+
+sub get_driver {
+ my ($self) = @_;
+ $self->{device}{driver};
+}
+
+sub get_interface {
+ my ($_self) = @_;
+ die "unable to get interface";
+}
+
+sub get_metric { 60 }
+
+sub get_up_timeout { 10 }
+
+sub get_status {
+ my ($self) = @_;
+ require network::tools;
+ my ($_is_up, $gw_address) = network::tools::get_interface_status($self->get_interface);
+ $self->{status} = to_bool($gw_address);
+}
+
+=item get_status_icon()
+
+Get status icon path (connected/disconnected/unconfigured)
+The file may not exist
+
+=cut
+
+sub get_status_icon {
+ my ($self) = @_;
+ my $icon = $self->get_type_icon;
+ my $status = $self->get_interface ? $self->get_status ? "on" : "off" : "w";
+ $icon . "-" . $status;
+}
+
+sub get_ifcfg_bool {
+ my ($self, $field) = @_;
+ defined $self->{ifcfg}{$field} ? text2bool($self->{ifcfg}{$field}) : undef;
+}
+
+sub get_selected_network {
+ my ($self) = @_;
+ exists $self->{networks}{$self->{network}} && $self->{networks}{$self->{network}};
+}
+
+sub selected_network_is_configured {
+ my ($self) = @_;
+
+ my $network = $self->get_selected_network or return;
+ $self->network_is_configured($network);
+}
+
+sub load_interface_settings {
+ my ($self) = @_;
+ require network::network;
+ my $file = network::network::get_ifcfg_file($self->get_interface);
+ $self->{ifcfg} = { getVarsFromSh($file) };
+ $self->{vpn_list} = [ map { $_->get_configured_connections } network::vpn->list_types ];
+ $self->{control}{onboot} = $self->get_ifcfg_bool('ONBOOT');
+ $self->{control}{userctl} = $self->get_ifcfg_bool('USERCTL');
+ $self->{control}{metric} = $self->{ifcfg}{METRIC};
+ $self->{control}{mtu} = $self->{ifcfg}{MTU};
+ $self->{control}{accounting} = $self->{ifcfg}{ACCOUNTING};
+ $self->{control}{nm_controlled} = $self->{ifcfg}{NM_CONTROLLED};
+ $self->{control}{uuid} = $self->{ifcfg}{UUID};
+ $self->{control}{name} = $self->{ifcfg}{NAME};
+ $self->{control}{last_connect} = $self->{ifcfg}{LAST_CONNECT};
+}
+
+#- override to return 1 if the connection network scan is slow
+sub network_scan_is_slow { 0 }
+#- override to return 1 if the hardware check is slow
+sub check_hardware_is_slow { 0 }
+#- override to return 1 if only one network is supported
+sub has_unique_network { 0 }
+
+sub get_network_access_settings_label { N("Network access settings") }
+sub get_access_settings_label { N("Access settings") }
+sub get_address_settings_label { N("Address settings") }
+
+#- check that $self->can('get_providers') first
+sub guess_provider_settings {
+ my ($self) = @_;
+ require lang;
+ my @providers_data = $self->get_providers;
+ my $locale_country = lang::c2name(ref($::o) && $::o->{locale}{country} || lang::read()->{country});
+ my $separator = $providers_data[1];
+ $self->{provider_name} ||= find { /^\Q$locale_country$separator\E/ } sort(keys %{$providers_data[0]});
+}
+
+sub set_provider {
+ my ($self) = @_;
+ if ($self->{provider_name} ne N("Unlisted - edit manually")) {
+ my @providers_data = $self->get_providers;
+ $self->{provider} = $providers_data[0]{$self->{provider_name}};
+ $self->apply_provider_settings($net);
+ }
+}
+
+sub apply_provider_settings {
+ my ($self, $net) = @_;
+ $self->guess_protocol($net) if $self->can('guess_protocol');
+ $self->guess_access_settings('provider_only') if $self->can('guess_access_settings');
+}
+
+#- check that $self->can('get_providers') first
+sub get_provider_settings {
+ my ($self) = @_;
+ my @providers_data = $self->get_providers;
+ [
+ {
+ type => "list", val => \$self->{provider_name}, separator => $providers_data[1],
+ list => [ N("Unlisted - edit manually"), sort(keys %{$providers_data[0]}) ], sort => 0,
+ changed => sub { $self->set_provider },
+ },
+ ];
+}
+
+#- check that $self->can('get_protocols') first
+sub get_protocol_settings {
+ my ($self) = @_;
+ my $protocols = $self->get_protocols;
+ [
+ {
+ val => \$self->{protocol}, type => 'list',
+ list => [ sort { $protocols->{$a} cmp $protocols->{$b} } keys %$protocols ],
+ format => sub { $protocols->{$_[0]} },
+ }
+ ];
+}
+
+sub guess_network_control_settings {
+ my ($self) = @_;
+ $self->{control}{vpn} = find {
+ $self->{ifcfg}{VPN_TYPE} eq $_->get_type &&
+ $self->{ifcfg}{VPN_NAME} eq $_->get_name;
+ } @{$self->{vpn_list}};
+}
+
+sub get_network_control_settings {
+ my ($self) = @_;
+ [
+ if_(@{$self->{vpn_list}},
+ { label => N("VPN connection"), val => \$self->{control}{vpn},
+ list => [ undef, @{$self->{vpn_list}} ],
+ format => sub { defined $_[0] ? $_[0]->get_label : N("None") } }),
+ ];
+}
+
+sub guess_control_settings {
+ my ($self) = @_;
+ $self->{control}{metric} ||= $self->get_metric;
+}
+
+sub get_control_settings {
+ my ($self) = @_;
+ [
+ { text => N("Allow users to manage the connection"), val => \$self->{control}{userctl}, type => "bool" },
+ { text => N("Start the connection at boot"), val => \$self->{control}{onboot}, type => "bool" },
+ { text => N("Enable traffic accounting"), val => \$self->{control}{accounting}, type => "bool" },
+ { text => N("Allow interface to be controlled by Network Manager"), val => \$self->{control}{nm_controlled}, type => "bool" },
+ { label => N("Metric"), val => \$self->{control}{metric}, advanced => 1 },
+ { label => N("MTU"), val => \$self->{control}{mtu}, advanced => 1,
+ help => N("Maximum size of network message (MTU). If unsure, left blank.") },
+ ];
+}
+
+sub build_ifcfg_settings {
+ my ($self, $o_options) = @_;
+ put_in_hash($o_options, {
+ DEVICE => $self->get_interface,
+ ONBOOT => bool2yesno($self->{control}{onboot}),
+ ACCOUNTING => bool2yesno($self->{control}{accounting}),
+ NM_CONTROLLED => bool2yesno($self->{control}{nm_controlled}),
+ USERCTL => bool2yesno($self->{control}{userctl}),
+ METRIC => $self->{control}{metric},
+ MTU => $self->{control}{mtu},
+ UUID => $self->{control}{uuid},
+ NAME => $self->{control}{name},
+ LAST_CONNECT => $self->{control}{last_connect},
+ VPN_TYPE => defined $self->{control}{vpn} && $self->{control}{vpn}->get_type,
+ VPN_NAME => defined $self->{control}{vpn} && $self->{control}{vpn}->get_name,
+ #- FIXME: add MS_DNSx variables if DNS servers are specified
+ });
+}
+
+sub write_settings {
+ my ($self, $o_net, $_o_modules_conf) = @_;
+ require network::network;
+ my $file = network::network::get_ifcfg_file($self->get_interface);
+ network::network::write_interface_settings($self->build_ifcfg_settings, $file);
+ if ($self->{address}{hostname}) {
+ $o_net->{network}{HOSTNAME} = $self->{address}{hostname} if $o_net;
+ network::network::write_hostname($self->{address}{hostname});
+ }
+ network::network::write_network_conf($o_net) if $o_net;
+ require network::shorewall;
+ network::shorewall::update_interfaces_list($self->get_interface);
+ network::network::reload_net_applet();
+}
+
+sub probed_networks {
+ my ($self) = @_;
+ $self->{probed_networks} = 1;
+}
+
+sub connect {
+ my ($self) = @_;
+ require network::tools;
+ network::tools::start_interface($self->get_interface, 0);
+}
+
+sub disconnect {
+ my ($self) = @_;
+ require network::tools;
+ network::tools::stop_interface($self->get_interface, 0);
+}
+
+sub setup_thirdparty {
+ my ($self, $in) = @_;
+ my $driver = $self->get_driver;
+ # FIXME: weird return code
+ $driver && $self->can('get_thirdparty_settings') or return 1;
+ require network::thirdparty;
+ $self->{thirdparty} = network::thirdparty::apply_settings($in, ref $self, $self->get_thirdparty_settings, $driver);
+ $self->{device} = $self->{thirdparty}{device} if $self->{thirdparty} && $self->{thirdparty}{device};
+ $self->{thirdparty};
+}
+
+sub prepare_device {
+ my ($self) = @_;
+ my $driver = $self->get_driver;
+ if ($driver) {
+ require modules;
+ eval { modules::load($driver) };
+ }
+}
+
+#- status messages can be sent using mdv-network-event
+sub get_status_message {
+ my ($self, $status) = @_;
+ my $interface = $self->get_interface;
+ {
+ link_up => N("Link detected on interface %s", $interface),
+ link_down => N("Link beat lost on interface %s", $interface),
+ }->{$status};
+}
+
+=head2 Pure virtual private instance methods
+
+=over
+
+=item _get_type_icon
+
+Get the icon prefix for the connection type
+
+=back
+
+=cut
+
+1;
diff --git a/lib/network/connection/.perl_checker b/lib/network/connection/.perl_checker
new file mode 100644
index 0000000..80deab8
--- /dev/null
+++ b/lib/network/connection/.perl_checker
@@ -0,0 +1 @@
+Basedir ../../..
diff --git a/lib/network/connection/cable.pm b/lib/network/connection/cable.pm
new file mode 100644
index 0000000..a81ae06
--- /dev/null
+++ b/lib/network/connection/cable.pm
@@ -0,0 +1,74 @@
+package network::connection::cable;
+
+use base qw(network::connection::ethernet);
+
+use strict;
+use common;
+use modules;
+use detect_devices;
+
+sub get_type_name() { N("Cable") }
+sub get_type_description() { N("Cable modem") }
+sub _get_type_icon() { 'cablemodem' }
+sub get_metric { 20 }
+
+sub handles_ifcfg {
+ my ($_class, $_ifcfg) = @_;
+ 0;
+}
+
+my $bpalogin_file = '/etc/bpalogin.conf';
+
+sub guess_protocol {
+ my ($self) = @_;
+ $self->{protocol} = 'dhcp';
+}
+
+sub guess_access_settings {
+ my ($self) = @_;
+ $self->{access}{use_bpalogin} = -e $::prefix . $bpalogin_file;
+ if ($self->{access}{use_bpalogin}) {
+ foreach (cat_($::prefix . $bpalogin_file)) {
+ /^username (.*)/ and $self->{access}{login} = $1;
+ /^password (.*)/ and $self->{access}{password} = $1;
+ }
+ }
+}
+
+sub get_access_settings {
+ my ($self) = @_;
+ my %auth = (
+ 0 => N("None"),
+ 1 => N("Use BPALogin (needed for Telstra)"),
+ );
+ [
+ { label => N("Authentication"), type => "list", val => \$self->{access}{use_bpalogin},
+ list => [ sort keys %auth ], format => sub { $auth{$_[0]} } },
+ { label => N("Account Login (user name)"), val => \$self->{access}{login},
+ disabled => sub { !$self->{access}{use_bpalogin} } },
+ { label => N("Account Password"), val => \$self->{access}{password}, hidden => 1,
+ disabled => sub { !$self->{access}{use_bpalogin} } },
+ ];
+}
+
+sub write_settings {
+ my ($self, $o_net, $o_modules_conf) = @_;
+ if ($self->{access}{use_bpalogin}) {
+ substInFile {
+ s/username\s+.*\n/username $self->{access}{login}\n/;
+ s/password\s+.*\n/password $self->{access}{password}\n/;
+ } $::prefix . $bpalogin_file;
+ }
+ services::set_status("bpalogin", $self->{access}{use_bpalogin});
+ $self->SUPER::write_settings($o_net, $o_modules_conf);
+}
+
+sub install_packages {
+ my ($self, $in) = @_;
+ if ($self->{access}{use_bpalogin}) {
+ $in->do_pkgs->ensure_is_installed('bpalogin', '/usr/sbin/bpalogin') or return;
+ }
+ $self->SUPER::install_packages($in);
+}
+
+1;
diff --git a/lib/network/connection/cellular.pm b/lib/network/connection/cellular.pm
new file mode 100644
index 0000000..5bb2259
--- /dev/null
+++ b/lib/network/connection/cellular.pm
@@ -0,0 +1,99 @@
+package network::connection::cellular;
+
+use base qw(network::connection::ppp);
+
+use strict;
+use common;
+
+my $cellular_d = "/etc/sysconfig/network-scripts/cellular.d";
+
+sub get_providers {
+ # manually-defined providers
+ require network::connection::providers::cellular;
+ # providers imported from mobile-broadband-provider-info
+ require network::connection::providers::cellular_extra;
+ # combine custom providers with m.b.p.i. imported ones,
+ # filtering out CDMA-only providers which we do not support for now
+ my %providers = (
+ %network::connection::providers::cellular::data,
+ grep_each{!$::b->{cdma} } %network::connection::providers::cellular_extra::data
+ );
+ (\%providers, '|');
+}
+
+sub get_cellular_settings_file {
+ my ($self) = @_;
+ my $network = $self->get_selected_network or return;
+ $::prefix . $cellular_d . '/' . $network->{name};
+}
+
+sub load_cellular_settings {
+ my ($self) = @_;
+ my $file = $self->get_cellular_settings_file or return;
+ -f $file && { getVarsFromSh($file) };
+}
+
+sub network_is_configured {
+ my ($self, $_network) = @_;
+ #- only one network is supported, assume it is configured if settings are available
+ defined($self->load_cellular_settings);
+}
+
+sub write_cellular_settings {
+ my ($self) = @_;
+ my $file = $self->get_cellular_settings_file or return;
+ setVarsInShMode($file, 0600, { map { (uc($_) => $self->{access}{$_}) } qw(login password apn) });
+}
+
+sub guess_apn_from_chat {
+ my ($self) = @_;
+ my $chat = cat_($::prefix . $self->get_chat_file);
+ my $chat_apn = $chat =~ /\bAT\+CGDCONT=\d+,"IP","([^"]+)"/ && $1;
+}
+
+sub guess_provider_settings {
+ my ($self) = @_;
+ my $settings = $self->load_cellular_settings;
+ my $apn = $settings && $settings->{APN} || $self->guess_apn_from_chat;
+ if ($apn) {
+ my @providers_data = $self->get_providers;
+ $self->{provider_name} ||= find { $providers_data[0]{$_}{apn} eq $apn } keys %{$providers_data[0]};
+ return;
+ }
+ $self->SUPER::guess_provider_settings;
+}
+
+sub guess_access_settings {
+ my ($self, $o_provider_only) = @_;
+ my $settings = !$o_provider_only && $self->load_cellular_settings || {};
+ $self->{access}{$_} = $settings->{uc($_)} || $self->{provider}{$_} foreach qw(login password apn);
+}
+
+sub get_access_settings {
+ my ($self) = @_;
+ [
+ { label => N("Access Point Name"), val => \$self->{access}{apn} },
+ @{$self->SUPER::get_access_settings},
+ ];
+}
+
+sub set_ppp_settings {
+ my ($self) = @_;
+ $self->{access}{use_chat} = 1;
+ $self->{access}{dial_number} = !$self->{access}{no_dial} && "*99***$self->{access}{cid}#";
+}
+
+sub write_settings {
+ my ($self) = @_;
+ $self->write_cellular_settings;
+ $self->set_ppp_settings;
+ $self->SUPER::write_settings;
+}
+
+sub apply_network_selection {
+ my ($self) = @_;
+ $self->set_ppp_settings;
+ $self->write_ppp_settings;
+}
+
+1;
diff --git a/lib/network/connection/cellular_bluetooth.pm b/lib/network/connection/cellular_bluetooth.pm
new file mode 100644
index 0000000..5c99b63
--- /dev/null
+++ b/lib/network/connection/cellular_bluetooth.pm
@@ -0,0 +1,103 @@
+package network::connection::cellular_bluetooth;
+
+use base qw(network::connection::cellular);
+
+use strict;
+use common;
+
+my $rfcomm_dev_prefix = "/dev/rfcomm";
+
+sub get_type_name { N("Bluetooth") }
+sub get_type_description { N("Bluetooth Dial Up Networking") }
+sub _get_type_icon { 'bluetooth' }
+sub get_devices {
+ my ($_class, %options) = @_;
+ ($options{fast_only} ? () : search_services('DUN'));
+}
+
+sub get_metric { 45 }
+sub get_interface { "ppp0" }
+
+sub get_packages { 'bluez', 'ppp' }
+
+sub get_rfcomm_device {
+ my ($self) = @_;
+ $self->{rfcomm_device} ||= find { ! -e ($rfcomm_dev_prefix . $_) } 0 .. 99;
+}
+
+sub get_tty_device {
+ my ($self) = @_;
+ $rfcomm_dev_prefix . $self->get_rfcomm_device;
+}
+
+# http://www.hingston.demon.co.uk/mike/nokia6680.html
+# http://kapsi.fi/~mcfrisk/linux_gprs.html
+# GPRS specific commands http://www.phonestar.com.my/s_at_10.html
+
+sub search_services {
+ my ($service_type) = @_;
+ my (@services);
+ my $service = {};
+ my ($key, $value);
+ my $push_service = sub { push @services, $service if exists $service->{class} };
+ my $use_key = sub { $key = $_[0]; undef $value };
+ foreach (run_program::rooted_get_stdout($::prefix, 'sdptool', 'search', $service_type)) {
+ if (/^Searching for $service_type on (.+) \.\.\.$/) {
+ $push_service->();
+ $service = { addr => $1 };
+ } elsif (/^Service Name:\s+(.*)$/) {
+ $service->{name} = $1;
+ } elsif (/^Service Provider:\s+(.*)$/) {
+ $service->{name} = $1;
+ } elsif (/^\s*Channel:\s*(\d+)$/) {
+ $service->{channel} = $1;
+ } elsif (/^Service Class ID List/) {
+ $use_key->('class');
+ } else {
+ $value = chomp_($_);
+ }
+ if ($key && $value) {
+ $service->{$key} = $value;
+ $use_key->(undef);
+ }
+ }
+ $push_service->();
+ my %names;
+ foreach (@services) {
+ $names{$_->{addr}} ||= chomp_(run_program::rooted_get_stdout($::prefix, 'hcitool', 'name', $_->{addr}));
+ $_->{description} = $names{$_->{addr}};
+ }
+ @services;
+}
+
+sub set_ppp_settings {
+ my ($self) = @_;
+
+ $self->{access}{cid} = 1;
+ $self->{access}{at_commands} = [ qq(AT+CGDCONT=$self->{access}{cid},"IP","$self->{access}{apn}") ];
+
+ $self->SUPER::set_ppp_settings;
+}
+
+sub write_settings {
+ my ($self) = @_;
+
+ my $dev = $self->get_rfcomm_device;
+ output("$::prefix/etc/bluetooth/rfcomm.conf", qq(
+rfcomm$dev {
+ bind yes;
+ device $self->{device}{addr};
+ channel $self->{device}{channel};
+ comment "Dial-up networking";
+}
+));
+
+ $self->SUPER::write_settings;
+}
+
+sub prepare_connection {
+ my ($self) = @_;
+ run_program::rooted_get_stdout($::prefix, 'rfcomm', 'bind', $self->get_rfcomm_device);
+}
+
+1;
diff --git a/lib/network/connection/cellular_card.pm b/lib/network/connection/cellular_card.pm
new file mode 100644
index 0000000..0fc3fbf
--- /dev/null
+++ b/lib/network/connection/cellular_card.pm
@@ -0,0 +1,278 @@
+package network::connection::cellular_card;
+
+use base qw(network::connection::cellular);
+
+use strict;
+use common;
+
+my $wrong_pin_error = N_("Wrong PIN number format: it should be 4 digits.");
+
+sub get_type_name() { N("GPRS/Edge/3G") }
+sub _get_type_icon() { 'cellular' }
+sub get_devices() {
+ require detect_devices;
+ my @maybe_usbserial_modules = ('usbserial_generic', 'unknown');
+ my @serial = grep { $_->{description} =~ /GPRS|EDGE|3G|UMTS|H.DPA|CDMA/i } detect_devices::matching_driver('serial_cs', 'usbserial', @maybe_usbserial_modules);
+ member($_->{driver}, @maybe_usbserial_modules) and $_->{driver} = 'usbserial' foreach @serial;
+ #- cdc_acm can not be listed directly in network/cellular, it is already in network/isdn
+ @serial, detect_devices::probe_category('network/cellular'), detect_devices::matching_driver('cdc_acm');
+}
+sub get_metric { 40 }
+
+sub get_packages { 'comgt', 'ppp' }
+
+sub handles_ifcfg {
+ my ($_class, $ifcfg) = @_;
+ exists $ifcfg->{CELLULAR_CID};
+}
+
+my @thirdparty_settings = (
+ {
+ name => 'nozomi',
+ description => 'Option GlobeTrotter 3G/EDGE and FUSION+',
+ url => 'http://www.pharscape.org/',
+ kernel_module => 1,
+ },
+ {
+ name => 'hso',
+ description => 'Option High Speed Mobile Devices',
+ url => 'http://www.pharscape.org/',
+ kernel_module => 1,
+ tools => {
+ package => 'hso-rezero',
+ test_file => '/usr/sbin/rezero',
+ },
+ },
+);
+
+sub get_thirdparty_settings() {
+ \@thirdparty_settings;
+}
+
+sub guess_hardware_settings {
+ my ($self) = @_;
+ $self->{hardware}{pin} ||= chomp_(cat_("/etc/sysconfig/network-scripts/pin-" . $self->get_interface));
+}
+
+sub get_interface {
+ my ($self) = @_;
+ $self->get_driver eq "hso" ?
+ "hso0" :
+ "ppp0";
+}
+
+sub get_tty_device {
+ my ($self) = @_;
+
+ my $tty_interface = 0;
+ my %udev_env = map { if_(/^([^=]*)=(.*)$/, $1 => $2) } chomp_(run_program::get_stdout("udevadm info --query=property --path=$self->{device}{sysfs_device}"));
+
+ if ($udev_env{USB_MODEM_INTERFACE}) {
+ my $dev_sys_path = $self->{device}->{sysfs_device};
+ my $cfg = chomp_(cat_($dev_sys_path . "/bConfigurationValue"));
+ my $tty_usb = basename(glob_("$dev_sys_path/" .
+ $self->{device}->{pci_bus} . "-" .
+ ($self->{device}->{usb_port} + 1) . ":$cfg." .
+ $udev_env{USB_MODEM_INTERFACE} . "/ttyUSB*"));
+ if ($tty_usb) {
+ $tty_usb =~ s/ttyUSB//;
+ $tty_interface = $tty_usb;
+ }
+ } else {
+ # if no usb interface for tty port given, use first one
+ my @intfs = glob_("$self->{device}->{sysfs_device}/" .
+ $self->{device}->{pci_bus} . "-" .
+ ($self->{device}->{usb_port} + 1) . ":*");
+ foreach (@intfs) {
+ my $tty_usb = basename(glob_("$_/tty*"));
+ if ($tty_usb) {
+ $tty_usb =~ s/tty[a-zA-Z]*//;
+ $tty_interface = $tty_usb;
+ last;
+ }
+ }
+ }
+
+ $self->{device}{device} ?
+ "/dev/" . $self->{device}{device} :
+ $self->get_driver eq "nozomi" ?
+ "/dev/noz" . $tty_interface :
+ $self->get_driver eq "cdc_acm" ?
+ "/dev/ttyACM" . $tty_interface :
+ $self->get_driver eq "hso" ?
+ "/dev/ttyHS" . $tty_interface :
+ "/dev/ttyUSB" . $tty_interface;
+}
+
+sub get_control_device {
+ my ($self) = @_;
+ my $tty_device = $self->get_tty_device;
+ if ($tty_device eq "/dev/ttyUSB0") {
+ for my $id (2, 1) {
+ my $usb_control_device = "/dev/ttyUSB" . $id;
+ return $usb_control_device if -e $usb_control_device;
+ }
+ }
+ $tty_device;
+}
+
+sub network_scan_is_slow() { 1 }
+sub check_hardware_is_slow() { 1 }
+sub has_unique_network() { 1 }
+
+sub get_networks {
+ my ($self) = @_;
+ my $cmd = 'comgt -d ' . $self->get_control_device;
+ my ($network, $state) = `$cmd reg` =~ /^Registered on \w+ network: "(.*)",(\d+)$/m;
+ my ($strength) = `$cmd sig` =~ /^Signal Quality:\s+(\d+),\d+$/;
+ $self->probed_networks;
+ $self->{networks} = $network && {
+ $network => {
+ name => $network,
+ signal_strength => $strength * 5,
+ current => $state == 2,
+ }
+ };
+}
+
+sub get_hardware_settings {
+ my ($self) = @_;
+ [ { label => N("PIN number (4 digits). Leave empty if PIN is not required."), val => \$self->{hardware}{pin}, hidden => 1 } ];
+}
+
+sub check_hardware_settings {
+ my ($self) = @_;
+ if ($self->{hardware}{pin} !~ /(^$|^[0-9]{4}$)/) {
+ $self->{hardware}{error} = translate($wrong_pin_error);
+ return 0;
+ }
+ 1;
+}
+
+sub get_peer_default_options {
+ my ($self) = @_;
+ $self->SUPER::get_peer_default_options,
+ "noccp", # disable CCP to avoid warning messages
+ "debug";
+}
+
+sub build_peer {
+ my ($self) = @_;
+ $self->SUPER::build_peer;
+ #- don't run comgt for now, it hangs on ttyUSB0 devices when run from pppd
+ #- $self->{access}{peer}->{init} = "comgt -d $dev < $pin_file"
+}
+
+sub set_ppp_settings {
+ my ($self) = @_;
+ $self->{access}{no_dial} = $self->get_driver eq "hso";
+ $self->{access}{cid} = 3;
+
+ $self->{access}{at_commands} = [
+ "AT+CPIN?",
+ # Set +CGEE to 2
+ "AT+CMEE=2",
+ qq(AT+CGDCONT=$self->{access}{cid},"IP","$self->{access}{apn}"),
+ # Setup +CGEQREG (QoS, don't set it for now)
+ # qq(AT+CGEQREQ=3,3,64,384,0,0,2,0,"0E0","0E0",3,0,0),
+ # Attached to network, will return 1
+ "AT+CGATT?",
+ if_($self->get_driver eq "hso", ""),
+ ];
+
+ $self->SUPER::set_ppp_settings;
+}
+
+sub write_settings {
+ my ($self) = @_;
+
+ my $interface = $self->get_interface;
+ my $pin_file = "/etc/sysconfig/network-scripts/pin-$interface";
+ output_with_perm($pin_file, 0600, $self->{hardware}{pin} . "\n");
+
+ $self->SUPER::write_settings;
+}
+
+sub prepare_device {
+ my ($self) = @_;
+
+ my $driver = $self->get_driver;
+ require modules;
+ my $modules_conf = ref($::o) && $::o->{modules_conf} || modules::any_conf->read;
+ modules::load_and_configure($modules_conf, $driver,
+ if_($driver eq 'usbserial', join(
+ ' ',
+ "vendor=0x" . sprintf("%04x", $self->{device}{vendor}),
+ "product=0x" . sprintf("%04x", $self->{device}{id}))));
+ $modules_conf->write if !ref $::o;
+ sleep 2 if $driver eq 'usbserial';
+}
+
+sub check_device {
+ my ($self) = @_;
+
+ my $dev = $self->get_tty_device;
+ if (! -e $dev) {
+ $self->{device}{error} = N("Unable to open device %s", $dev);
+ return;
+ }
+
+ 1;
+}
+
+sub check_hardware {
+ my ($self) = @_;
+ to_bool(run_program::rooted($::prefix, 'comgt', '>', '/dev/null', '-d', $self->get_control_device, 'PIN'));
+}
+
+sub configure_hardware {
+ my ($self) = @_;
+
+ my $device_ready = 0;
+
+ require IPC::Open2;
+ require IO::Select;
+ require c;
+ use POSIX qw(:errno_h);
+
+ my $pid = IPC::Open2::open2(my $cmd_out, my $cmd_in, 'comgt', '-d', $self->get_control_device);
+ common::nonblock($cmd_out);
+ my $selector = IO::Select->new($cmd_out);
+ my $already_entered_pin;
+
+ while ($selector->can_read) {
+ local $_;
+ my $rv = sysread($cmd_out, $_, 512);
+ $rv == 0 and $selector->remove($cmd_out);
+ if (/^\s*\*\*\*SIM ERROR\*\*\*/m) {
+ $self->{hardware}{error} = N("Please check that your SIM card is inserted.");
+ last;
+ } elsif (/^Enter PIN number:/m) {
+ $self->{hardware}{pin} or last;
+ if ($already_entered_pin) {
+ $self->{hardware}{error} = translate($wrong_pin_error);
+ last;
+ }
+ $already_entered_pin = 1;
+ print $cmd_in $self->{hardware}{pin} . "\n";
+ } elsif (/^ERROR entering PIN/m) {
+ $self->{hardware}{error} = N("You entered a wrong PIN code.
+Entering the wrong PIN code multiple times may lock your SIM card!");
+ last;
+ } elsif (/^Waiting for Registration/m) {
+ #- the card seems to be reset if comgt is killed right here, wait a bit
+ sleep 1;
+ #- don't wait the full scan
+ $device_ready = 1;
+ last;
+ }
+ }
+ kill 'TERM', $pid;
+ close($cmd_out);
+ close($cmd_in);
+ waitpid($pid, 0);
+
+ $device_ready;
+}
+
+1;
diff --git a/lib/network/connection/dvb.pm b/lib/network/connection/dvb.pm
new file mode 100644
index 0000000..c5f8ff6
--- /dev/null
+++ b/lib/network/connection/dvb.pm
@@ -0,0 +1,70 @@
+package network::connection::dvb;
+
+use base qw(network::connection::ethernet);
+
+use strict;
+use common;
+use modules;
+
+sub get_type_name() { N("DVB") }
+sub get_type_description() { N("Satellite (DVB)") }
+sub _get_type_icon() { 'dvb' }
+
+sub get_devices() {
+ require detect_devices;
+ detect_devices::probe_category("multimedia/dvb");
+}
+
+sub get_metric { 15 }
+
+sub handles_ifcfg {
+ my ($_class, $ifcfg) = @_;
+ exists $ifcfg->{DVB_ADAPTER_ID};
+}
+
+sub get_interface {
+ my ($self) = @_;
+ defined $self->{hardware}{adapter_id} && defined $self->{hardware}{network_demux} or return "dvb";
+ 'dvb' . $self->{hardware}{adapter_id} . '_' . $self->{hardware}{network_demux};
+}
+
+sub get_dvb_device {
+ find { sysopen(undef, $_, c::O_RDWR() | c::O_NONBLOCK()) } glob("/dev/dvb/adapter*/net*");
+}
+
+sub load_interface_settings {
+ my ($self) = @_;
+ $self->guess_hardware_settings; #- so that matching interface settings can be loaded
+ $self->network::connection::load_interface_settings;
+ $self->{hardware}{adapter_id} = $self->{ifcfg}{DVB_ADAPTER_ID};
+ $self->{hardware}{network_demux} = $self->{ifcfg}{DVB_NETWORK_DEMUX};
+ $self->{hardware}{network_pid} = $self->{ifcfg}{DVB_NETWORK_PID};
+}
+
+sub guess_hardware_settings {
+ my ($self) = @_;
+ my $device = get_dvb_device() or return;
+ ($self->{hardware}{adapter_id}, $self->{hardware}{network_demux}) = $device =~ m,/dev/dvb/adapter(\d+)/net(\d+),;
+}
+
+sub get_hardware_settings {
+ my ($self) = @_;
+ [
+ { label => N("Adapter card"), val => \$self->{hardware}{adapter_id} },
+ { label => N("Net demux"), val => \$self->{hardware}{network_demux} },
+ { label => N("PID"), val => \$self->{hardware}{network_pid} },
+ ];
+}
+
+sub build_ifcfg_settings {
+ my ($self) = @_;
+ my $settings = {
+ DVB_ADAPTER_ID => qq("$self->{hardware}{adapter_id}"),
+ DVB_NETWORK_DEMUX => qq("$self->{hardware}{network_demux}"),
+ DVB_NETWORK_PID => qq("$self->{hardware}{network_pid}"),
+ MII_NOT_SUPPORTED => "yes",
+ };
+ $self->SUPER::build_ifcfg_settings($settings);
+}
+
+1;
diff --git a/lib/network/connection/ethernet.pm b/lib/network/connection/ethernet.pm
new file mode 100644
index 0000000..7b76396
--- /dev/null
+++ b/lib/network/connection/ethernet.pm
@@ -0,0 +1,552 @@
+package network::connection::ethernet; # $Id: ethernet.pm 147431 2007-03-21 17:06:09Z blino $
+
+use base qw(network::connection);
+
+use strict;
+use common;
+use network::tools;
+
+our @dhcp_clients = qw(dhclient dhcpcd pump dhcpxd);
+
+sub get_type_name() { N("Ethernet") }
+sub get_type_description() { N("Wired (Ethernet)") }
+sub _get_type_icon() { 'ethernet' }
+
+sub get_devices() {
+ #require list_modules;
+ #- FIXME: try to use list_modules::ethernet_categories() (but remove wireless stuff)
+ require detect_devices;
+ my @devices = detect_devices::probe_category('network/main|gigabit|pcmcia|tokenring|usb|firewire');
+ my @lan = grep { detect_devices::is_lan_interface($_) && !detect_devices::is_wireless_interface($_) } detect_devices::get_all_net_devices();
+ @devices, get_unlisted_devices(\@lan, \@devices);
+}
+
+sub get_unlisted_devices {
+ my ($interfaces, $listed_devices) = @_;
+ my @unlisted_interfaces = sort(difference2($interfaces, [ map { device_to_interface($_) } @$listed_devices ]));
+ map {
+ my %device = %{interface_to_device($_) || +{ description => $_ }};
+ $device{interface} = $_;
+ $device{description} = N("Virtual interface") if network::tools::is_virtual_interface($_);
+ \%device;
+ } @unlisted_interfaces;
+}
+
+sub handles_ifcfg {
+ my ($_class, $ifcfg) = @_;
+ require detect_devices;
+ detect_devices::is_lan_interface($ifcfg->{DEVICE});
+}
+
+sub is_gigabit {
+ my ($self) = @_;
+ require list_modules;
+ member($self->get_driver, list_modules::category2modules('network/gigabit'));
+}
+
+sub get_metric {
+ my ($self) = @_;
+ $self->is_gigabit ? 5 : 10;
+}
+
+sub get_interface {
+ my ($self) = @_;
+ $self->{device}{interface} ||= device_to_interface($self->{device});
+}
+
+sub check_device {
+ my ($self) = @_;
+ if (!$self->get_interface) {
+ $self->{device}{error} = N("Unable to find network interface for selected device (using %s driver).", $self->get_driver);
+ return 0;
+ }
+ return 1;
+}
+
+sub get_protocols() {
+ my $system_file = '/etc/sysconfig/drakx-net';
+ my %global_settings = getVarsFromSh($system_file);
+ +{
+ if_(!text2bool($global_settings{AUTOMATIC_ADDRESS}), static => N("Manual configuration")),
+ dhcp => N("Automatic IP (BOOTP/DHCP)"),
+ };
+}
+
+sub load_interface_settings {
+ my ($self) = @_;
+
+ $self->network::connection::load_interface_settings;
+ $self->map_ifcfg2config_settings;
+}
+
+sub map_ifcfg2config_settings {
+ my ($self) = @_;
+ $self->{protocol} = $self->{ifcfg}{BOOTPROTO};
+
+ $self->{address}{needhostname} = $self->get_ifcfg_bool('NEEDHOSTNAME');
+ $self->{address}{peerdns} = $self->get_ifcfg_bool('PEERDNS');
+ $self->{address}{peeryp} = $self->get_ifcfg_bool('PEERYP');
+ $self->{address}{peerntpd} = $self->get_ifcfg_bool('PEERNTPD');
+
+ $self->{address}{dhcp_client} = $self->{ifcfg}{DHCP_CLIENT};
+ $self->{address}{dhcp_hostname} = $self->{ifcfg}{DHCP_HOSTNAME};
+ $self->{address}{dhcp_timeout} = $self->{ifcfg}{DHCP_TIMEOUT};
+ $self->{address}{ip_address} = $self->{ifcfg}{IPADDR};
+ $self->{address}{netmask} = $self->{ifcfg}{NETMASK};
+ $self->{address}{gateway} = $self->{ifcfg}{GATEWAY};
+ $self->{address}{dns1} = $self->{ifcfg}{DNS1} || $self->{ifcfg}{MS_DNS1};
+ $self->{address}{dns2} = $self->{ifcfg}{DNS2} || $self->{ifcfg}{MS_DNS2};
+ $self->{address}{domain} = $self->{ifcfg}{DOMAIN};
+
+ my $blacklist_ifplugd = $self->get_ifcfg_bool('MII_NOT_SUPPORTED');
+ $self->{control}{use_ifplugd} = !$blacklist_ifplugd if defined $blacklist_ifplugd;
+ $self->{control}{ipv6_tunnel} = $self->get_ifcfg_bool('IPV6TO4INIT');
+}
+
+sub guess_protocol {
+ my ($self) = @_;
+ $self->{protocol} ||= 'dhcp';
+}
+
+sub guess_address_settings {
+ my ($self) = @_;
+ $self->{address}{dhcp_client} ||= find { -x "$::prefix/sbin/$_" } @dhcp_clients;
+ $self->{address}{peerdns} = 1 if !defined $self->{address}{peerdns};
+ $self->{address}{peeryp} = 1 if !defined $self->{address}{peeryp};
+ $self->supplement_address_settings;
+}
+
+sub supplement_address_settings {
+ my ($self) = @_;
+ if ($self->{protocol} eq 'static' && network::network::is_ip($self->{address}{ip_address})) {
+ require network::network;
+ $self->{address}{netmask} ||= network::network::netmask($self->{address}{ip_address});
+ # Bug #28033: don't guess default gateway and ns in static interfaces if
+ # user doesn't set one (otherwise we'll mess multi-interface systems)
+ #
+ #$self->{address}{gateway} ||= network::network::gateway($self->{address}{ip_address});
+ #$self->{address}{dns1} ||= network::network::dns($self->{address}{ip_address});
+ }
+}
+
+sub get_address_settings_label { N("IP settings") }
+
+sub get_address_settings {
+ my ($self, $o_show_all) = @_;
+ my $auto_dns = sub { $self->{protocol} eq 'dhcp' && $self->{address}{peerdns} };
+ my $not_static = sub { $self->{protocol} ne 'static' };
+ my $not_dhcp = sub { $self->{protocol} ne 'dhcp' };
+ [
+ if_($self->{protocol} eq 'static' || $o_show_all,
+ { label => N("IP address"), val => \$self->{address}{ip_address}, disabled => $not_static,
+ focus_out => sub {
+ $self->supplement_address_settings if $self->can('supplement_address_settings');
+ },
+ help => N("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).") },
+ { label => N("Netmask"), val => \$self->{address}{netmask}, disabled => $not_static },
+ { label => N("Gateway"), val => \$self->{address}{gateway}, disabled => $not_static },
+ ),
+ if_($self->{protocol} eq 'dhcp' || $o_show_all,
+ { text => N("Get DNS servers from DHCP"), val => \$self->{address}{peerdns}, type => "bool", disabled => $not_dhcp },
+ ),
+ { label => N("DNS server 1"), val => \$self->{address}{dns1}, disabled => $auto_dns },
+ { label => N("DNS server 2"), val => \$self->{address}{dns2}, disabled => $auto_dns },
+ { label => N("Search domain"), val => \$self->{address}{domain}, disabled => $auto_dns, advanced => 1,
+ help => N("By default search domain will be set from the fully-qualified host name") },
+ if_($self->{protocol} eq 'dhcp',
+ { label => N("DHCP client"), val => \$self->{address}{dhcp_client}, list => \@dhcp_clients, advanced => 1 },
+ { label => N("DHCP timeout (in seconds)"), val => \$self->{address}{dhcp_timeout}, advanced => 1 },
+ { text => N("Get YP servers from DHCP"), val => \$self->{address}{peeryp}, type => "bool", advanced => 1 },
+ { text => N("Get NTPD servers from DHCP"), val => \$self->{address}{peerntpd}, type => "bool", advanced => 1 },
+ { label => N("DHCP host name"), val => \$self->{address}{dhcp_hostname}, advanced => 1 },
+ #- FIXME: install zcip if not checked
+ if_(0, { text => N("Do not fallback to Zeroconf (169.254.0.0 network)"), type => "bool", val => \$self->{address}{skip_zeroconf}, advanced => 1 }),
+ ),
+ ];
+}
+
+sub check_address_settings {
+ my ($self, $net) = @_;
+
+ if ($self->{protocol} eq 'static') {
+ require network::network;
+ if (!network::network::is_ip($self->{address}{ip_address})) {
+ $self->{address}{error}{message} = N("IP address should be in format 1.2.3.4");
+ $self->{address}{error}{field} = \$self->{address}{ip_address};
+ return 0;
+ }
+ if (!network::network::is_ip($self->{address}{netmask})) {
+ $self->{address}{error}{message} = N("Netmask should be in format 255.255.224.0");
+ $self->{address}{error}{field} = \$self->{address}{netmask};
+ return 0;
+ }
+ if (network::network::is_ip_forbidden($self->{address}{ip_address})) {
+ $self->{address}{error}{message} = N("Warning: IP address %s is usually reserved!", $self->{address}{ip_address});
+ $self->{address}{error}{field} = \$self->{address}{ip_address};
+ return 0;
+ }
+ #- test if IP address is already used
+ if (my $conflict = find { text2bool($_->{ONBOOT}) && $_->{DEVICE} ne $self->get_interface && $_->{IPADDR} eq $self->{address}{ip_address} } values %{$net->{ifcfg}} ) {
+ # find out what connection we are conflicting with
+ my $conflict_device = $conflict->{DEVICE};
+
+ $self->{address}{error}{message} = N("%s is already used by a connection that starts on boot (%s). To use this address with this connection, first disable all other devices which use it, or configure them not to start at boot", $self->{address}{ip_address}, $conflict_device);
+ $self->{address}{error}{field} = \$self->{address}{ip_address};
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+sub guess_hostname_settings {
+ my ($self) = @_;
+ $self->{address}{needhostname} = 0 if !defined $self->{address}{needhostname};
+ if (!defined $self->{address}{hostname}) {
+ require network::network;
+ my $network = network::network::read_conf($::prefix . $network::network::network_file);
+ $self->{address}{hostname} = $network->{HOSTNAME};
+ }
+}
+
+# FIXME: add in drakroam/netcenter
+sub get_hostname_settings {
+ my ($self) = @_;
+ my $auto_hostname = sub { $self->{protocol} eq 'dhcp' && $self->{address}{needhostname} };
+ # configure the default hostname so the hostname setting should be more obvious to the users
+ $self->{address}{hostname} = 'localhost.localdomain' unless $self->{address}{hostname};
+ [
+ if_($self->{protocol} eq 'dhcp',
+ { text => N("Assign host name from DHCP server (or generate a unique one)"), val => \$self->{address}{needhostname}, type => "bool",
+ help => N("This will allow the server to attribute a name for this machine. If the server does not provides a valid host name, it will be generated automatically.")},
+ ),
+ { label => N("Host name"), val => \$self->{address}{hostname}, disabled => $auto_hostname,
+ help => N("You should define a hostname for this machine, which will identify this PC. Note that this hostname will be shared among all network connections. If left blank, 'localhost.localdomain' will be used.")},
+ ];
+}
+
+sub guess_control_settings {
+ my ($self) = @_;
+
+ $self->network::connection::guess_control_settings($self);
+
+ $self->{control}{onboot} = 1 if !defined $self->{control}{onboot};
+ $self->{control}{use_ifplugd} = !is_ifplugd_blacklisted($self->get_driver)
+ if !defined $self->{control}{use_ifplugd};
+}
+
+sub get_control_settings {
+ my ($self) = @_;
+ [
+ @{$self->network::connection::get_control_settings},
+ { text => N("Network Hotplugging"), val => \$self->{control}{use_ifplugd}, type => "bool",
+ #- FIXME: force ifplugd if wireless roaming is enabled
+ disabled => sub { $self->{control}{force_ifplugd} }, advanced => 1, },
+ #- FIXME: $need_network_restart = $ipv6_tunnel ^ text2bool($ethntf->{IPV6TO4INIT});
+ { text => N("Enable IPv6 to IPv4 tunnel"), val => \$self->{control}{ipv6_tunnel}, type => "bool", advanced => 1 },
+ ];
+}
+
+sub install_packages {
+ my ($self, $in) = @_;
+ if ($self->{protocol} eq 'dhcp') {
+ install_dhcp_client($in, $self->{address}{dhcp_client}) or return;
+ }
+ 1;
+}
+
+sub build_ifcfg_settings {
+ my ($self, $o_options) = @_;
+ my $settings = put_in_hash($o_options, {
+ BOOTPROTO => $self->{protocol},
+ IPADDR => $self->{address}{ip_address},
+ GATEWAY => $self->{address}{gateway},
+ NETMASK => $self->{address}{netmask},
+ NEEDHOSTNAME => bool2yesno($self->{address}{needhostname}),
+ PEERYP => bool2yesno($self->{address}{peeryp}),
+ PEERDNS => bool2yesno($self->{address}{peerdns}),
+ RESOLV_MODS => bool2yesno(!$self->{address}{peerdns} && ($self->{address}{dns1} || $self->{address}{dns2})),
+ PEERNTPD => bool2yesno($self->{address}{peerntpd}),
+ DHCP_CLIENT => $self->{address}{dhcp_client},
+ DHCP_HOSTNAME => $self->{address}{dhcp_hostname},
+ DHCP_TIMEOUT => $self->{address}{dhcp_timeout},
+ MII_NOT_SUPPORTED => bool2yesno(!$self->{control}{use_ifplugd}),
+ IPV6INIT => bool2yesno($self->{control}{ipv6_tunnel}),
+ IPV6TO4INIT => bool2yesno($self->{control}{ipv6_tunnel}),
+ DNS1 => $self->{address}{dns1},
+ DNS2 => $self->{address}{dns2},
+ DOMAIN => $self->{address}{domain},
+ LINK_DETECTION_DELAY => $self->get_link_detection_delay,
+ });
+ $self->network::connection::build_ifcfg_settings($settings);
+}
+
+sub write_settings {
+ my ($self, $o_net, $o_modules_conf) = @_;
+ if ($o_modules_conf) {
+ $o_modules_conf->set_alias($self->get_interface, $self->get_driver);
+ if ($self->{device}{sysfs_device}) {
+ my $modalias = chomp_(cat_($self->{device}{sysfs_device} . "/modalias"));
+ $o_modules_conf->set_alias($modalias, $self->get_driver) if $modalias;
+ }
+ }
+ $self->SUPER::write_settings($o_net, $o_modules_conf);
+ # update udev configuration
+ update_udev_net_config();
+}
+
+sub get_status_message {
+ my ($self, $status) = @_;
+ my $interface = $self->get_interface;
+ {
+ link_up => N("Link beat detected on interface %s", $interface),
+ link_down => N("Link beat lost on interface %s", $interface),
+ map { (
+ "$_->[0]_request" => N("Requesting a network address on interface %s (%s protocol)...", $interface, $_->[1]),
+ "$_->[0]_success" => N("Got a network address on interface %s (%s protocol)", $interface, $_->[1]),
+ "$_->[0]_failure" => N("Failed to get a network address on interface %s (%s protocol)", $interface, $_->[1]),
+ ) } ([ 'dhcp', 'DHCP' ], [ 'zcip', 'ZeroConf' ]),
+ }->{$status} || $self->network::connection::get_status_message($status);
+}
+
+use c;
+use detect_devices;
+use common;
+use run_program;
+
+sub install_dhcp_client {
+ my ($in, $client) = @_;
+ my %packages = (
+ "dhclient" => "dhcp-client",
+ );
+ #- use default dhcp client if none is provided
+ $client ||= $dhcp_clients[0];
+ $client = $packages{$client} if exists $packages{$client};
+ $in->do_pkgs->ensure_is_installed($client, undef, 1);
+}
+
+my @hwaddr_fields = qw(pci_domain pci_bus pci_device pci_function);
+
+sub are_same_HwIDs {
+ my ($device1, $device2) = @_;
+ every { $device1->{$_} == $device2->{$_} } @hwaddr_fields;
+}
+
+sub parse_hwaddr {
+ my ($hw_addr) = @_;
+ return if !$hw_addr;
+ my %device;
+ @device{@hwaddr_fields} = map { hex($_) } ($hw_addr =~ /([0-9a-f]+):([0-9a-f]+):([0-9a-f]+)\.([0-9a-f]+)/);
+ (every { defined $_ } keys %device) ? \%device : undef;
+}
+
+sub mapIntfToDevice {
+ my ($interface) = @_;
+ my $hw_addr = c::getHwIDs($interface);
+ return {} if $hw_addr =~ /^usb/;
+ my $device = parse_hwaddr($hw_addr);
+ $device ? grep { are_same_HwIDs($_, $device) } detect_devices::probeall() : {};
+}
+
+sub device_matches_interface_HwIDs {
+ my ($device, $interface) = @_;
+ my $hw_addr = c::getHwIDs($interface);
+ $hw_addr =~ /^usb/ and return;
+ my ($device2) = parse_hwaddr($hw_addr);
+ return if !$device2;
+ are_same_HwIDs($device, $device2);
+}
+
+sub get_interface_sysfs_path {
+ my ($interface) = @_;
+ $interface = network::tools::get_real_interface($interface);
+ my $dev_path = "/sys/class/net/$interface/device";
+ my $bus = detect_devices::get_sysfs_field_from_link($dev_path, "subsystem");
+ if ($bus eq 'ieee1394') {
+ my $child = first(glob("$dev_path/host_id/*-*"));
+ $dev_path = $child if $child;
+ }
+ $dev_path;
+}
+
+sub get_interface_ids {
+ my ($interface) = @_;
+ detect_devices::get_ids_from_sysfs_device(get_interface_sysfs_path($interface));
+}
+
+sub device_matches_interface {
+ my ($device, $interface) = @_;
+ detect_devices::device_matches_sysfs_ids($device, get_interface_ids($interface));
+}
+
+sub device_to_interface {
+ my ($device) = @_;
+ my @all_interfaces = detect_devices::get_net_interfaces();
+ my ($real, $other) = partition { network::tools::is_real_interface($_) } @all_interfaces;
+ find {
+ device_matches_interface_HwIDs($device, $_) ||
+ device_matches_interface($device, $_);
+ } @$real, @$other;
+}
+
+sub interface_to_device {
+ my ($interface) = @_;
+ my $sysfs_ids = get_interface_ids($interface);
+ find { detect_devices::device_matches_sysfs_ids($_, $sysfs_ids) } detect_devices::probeall();
+}
+
+sub interface_to_driver {
+ my ($interface) = @_;
+ my $dev_path = get_interface_sysfs_path($interface);
+ #- FIXME: use $bus and move in get_interface_sysfs_path if possible
+ my $child = -f "$dev_path/idVendor" && first(glob("$dev_path/*-*:*.*"));
+ $dev_path = $child if -f "$child/driver/module";
+ detect_devices::get_sysfs_field_from_link($dev_path, 'driver/module');
+}
+
+# return list of [ intf_name, module, device_description ] tuples such as:
+# [ "eth0", "3c59x", "3Com Corporation|3c905C-TX [Fast Etherlink]" ]
+#
+# this function try several method in order to get interface's driver and description in order to support both:
+# - hotplug managed devices (USB, firewire)
+# - special interfaces (IP aliasing, VLAN)
+sub get_eth_cards {
+ my ($o_modules_conf) = @_;
+
+ detect_devices::probeall_update_cache();
+ my @all_cards = detect_devices::get_lan_interfaces();
+
+ my @devs = detect_devices::pcmcia_probe();
+ my $saved_driver;
+ # compute device description and return (interface, driver, description) tuples:
+ return map {
+ my $interface = $_;
+ my $description;
+ # 1) get interface's driver through ETHTOOL ioctl:
+ my ($a, $detected_through_ethtool);
+ $a = c::getNetDriver($interface);
+ if ($a) {
+ $detected_through_ethtool = 1;
+ } elsif ($o_modules_conf) {
+ # 2) get interface's driver through module aliases:
+ $a = $o_modules_conf->get_alias($interface);
+ }
+
+ # workaround buggy drivers that returns a bogus driver name for the GDRVINFO command of the ETHTOOL ioctl:
+ my %fixes = (
+ "p80211_prism2_cs" => 'prism2_cs',
+ "p80211_prism2_pci" => 'prism2_pci',
+ "p80211_prism2_usb" => 'prism2_usb',
+ "ip1394" => "eth1394",
+ "DL2K" => "dl2k",
+ "orinoco" => undef, #- should be orinoco_{cs,nortel,pci,plx,tmd}
+ "hostap" => undef, #- should be hostap_{cs,pci,plx}
+ );
+ if (exists $fixes{$a}) {
+ $a = $fixes{$a};
+ $a or undef $detected_through_ethtool;
+ }
+
+ # 3) try to match a PCMCIA device for device description:
+ if (my $b = find { $_->{device} eq $interface } @devs) { # PCMCIA case
+ $a = $b->{driver};
+ $description = $b->{description};
+ } else {
+ # 4) try to lookup a device by hardware address for device description:
+ # maybe should have we try sysfs first for robustness?
+ my @devices = mapIntfToDevice($interface);
+ ($description) = $devices[0]{description} if @devices;
+ }
+ # 5) try to match a device through sysfs for driver & device description:
+ # (eg: ipw2100 driver for intel centrino do not support ETHTOOL)
+ if (!$description || !$a) {
+ my $drv = interface_to_driver($interface);
+ $a = $drv if $drv && !$detected_through_ethtool;
+ my $card = interface_to_device($interface);
+ $description ||= $card->{description} if $card;
+ }
+ # 6) try to match a device by driver for device description:
+ # (eg: madwifi, ndiswrapper, ...)
+ if (!$description) {
+ my @cards = grep { $_->{driver} eq ($a || $saved_driver) } detect_devices::probeall();
+ $description = $cards[0]{description} if @cards == 1;
+ }
+ $a and $saved_driver = $a; # handle multiple cards managed by the same driver
+ [ $interface, $saved_driver, if_($description, $description) ];
+ } @all_cards;
+}
+
+sub get_eth_cards_names {
+ my (@all_cards) = @_;
+ map { $_->[0] => join(': ', $_->[0], $_->[2]) } @all_cards;
+}
+
+#- returns (link_type, mac_address)
+sub get_eth_card_mac_address {
+ my ($intf) = @_;
+ #- don't look for 6 bytes addresses only because of various non-standard MAC addresses
+ `$::prefix/sbin/ip -o link show $intf 2>/dev/null` =~ m|.*link/(\S+)\s((?:[0-9a-f]{2}:?)+)\s|;
+}
+
+#- write interfaces MAC address in iftab
+sub update_iftab() {
+ #- skip aliases and vlan interfaces
+ foreach my $intf (grep { network::tools::is_real_interface($_) } detect_devices::get_lan_interfaces()) {
+ my ($link_type, $mac_address) = get_eth_card_mac_address($intf) or next;
+ #- do not write zeroed MAC addresses in iftab, it confuses ifrename
+ $mac_address =~ /^[0:]+$/ and next;
+ # ifrename supports alsa IEEE1394, EUI64 and IRDA
+ member($link_type, 'ether', 'ieee1394', 'irda', '[27]') or next;
+ substInFile {
+ s/^$intf\s+.*\n//;
+ s/^.*\s+$mac_address\n//;
+ $_ .= qq($intf mac $mac_address\n) if eof;
+ } "$::prefix/etc/iftab";
+ }
+}
+
+sub update_udev_net_config() {
+ my $lib = arch() =~ /x86_64/ ? "lib64" : "lib";
+ my $net_name_helper = "/lib/udev/write_net_rules";
+ my $udev_net_config = "$::prefix/etc/udev/rules.d/70-persistent-net.rules";
+ my @old_config = cat_($udev_net_config);
+ #- skip aliases and vlan interfaces
+ foreach my $intf (grep { network::tools::is_real_interface($_) } detect_devices::get_lan_interfaces()) {
+ (undef, my $mac_address) = get_eth_card_mac_address($intf) or next;
+ #- do not write zeroed MAC addresses
+ $mac_address =~ /^[0:]+$/ and next;
+ #- skip already configured addresses
+ any { !/^\s*#/ && /"$mac_address"/ } @old_config and next;
+ my $type = cat_("/sys/class/net/$intf/type") =~ /^\d+$/;
+ local $ENV{MATCHIFTYPE} = $type if $type;
+ local $ENV{INTERFACE} = $intf;
+ local $ENV{MATCHADDR} = $mac_address;
+ local $ENV{COMMENT} = "Drakx-net rule for $intf ($mac_address)";
+ run_program::rooted($::prefix, $net_name_helper, '>', '/dev/null', $mac_address);
+ }
+}
+
+# automatic net aliases configuration
+sub configure_eth_aliases {
+ my ($modules_conf) = @_;
+ foreach my $card (get_eth_cards($modules_conf)) {
+ $modules_conf->set_alias($card->[0], $card->[1]);
+ }
+ $::isStandalone and $modules_conf->write;
+ update_iftab();
+ update_udev_net_config();
+}
+
+sub get_link_detection_delay {
+ my ($self) = @_;
+ member($self->get_driver, qw(b44 forcedeth r8169 skge sky2 tg3 via_velocity e1000e)) && 6;
+}
+
+sub is_ifplugd_blacklisted {
+ my ($module) = @_;
+ !$module;
+}
+
+1;
diff --git a/lib/network/connection/isdn.pm b/lib/network/connection/isdn.pm
new file mode 100644
index 0000000..1b8debc
--- /dev/null
+++ b/lib/network/connection/isdn.pm
@@ -0,0 +1,230 @@
+package network::connection::isdn;
+
+use base qw(network::connection);
+
+use strict;
+use common;
+
+sub get_type_name { N("ISDN") }
+sub _get_type_icon { 'isdn' }
+
+sub get_devices {
+ require modules;
+ #- FIXME: module alias should be written when config is written only
+ @{detect_backend(modules::any_conf->read)};
+}
+sub get_metric { 30 }
+
+sub get_up_timeout { 20 }
+
+use network::connection::isdn::consts;
+use modules;
+use run_program;
+use log;
+use network::tools;
+use services;
+
+sub apply_config {
+ my ($in, $isdn) = @_;
+
+ $isdn = find_capi_card($isdn) if $isdn->{driver} eq "capidrv";
+ unload_connection($isdn);
+ install_packages($isdn, $in);
+ write_settings($isdn);
+ write_capi_conf($isdn) if $isdn->{driver} eq "capidrv";
+ prepare_connection($isdn);
+}
+
+sub write_settings {
+ my ($isdn) = @_;
+
+ output_with_perm("$::prefix/etc/isdn/profile/link/myisp", 0600,
+ qq(
+I4L_USERNAME="$isdn->{login}"
+I4L_SYSNAME=""
+I4L_LOCALMSN="$isdn->{phone_in}"
+I4L_REMOTE_OUT="$isdn->{phone_out}"
+I4L_DIALMODE="$isdn->{dialing_mode}"
+I4L_IDLETIME="$isdn->{huptimeout}"
+) . if_($isdn->{speed} =~ /128/, 'SLAVE="ippp1"
+'));
+ output "$::prefix/etc/isdn/profile/card/mycard",
+ qq(
+I4L_MODULE="$isdn->{driver}"
+I4L_TYPE="$isdn->{type}"
+I4L_IRQ="$isdn->{irq}"
+I4L_MEMBASE="$isdn->{mem}"
+I4L_PORT="$isdn->{io}"
+I4L_IO0="$isdn->{io0}"
+I4L_IO1="$isdn->{io1}"
+I4L_ID="HiSax"
+I4L_FIRMWARE="$isdn->{firmware}"
+I4L_PROTOCOL="$isdn->{protocol}"
+);
+
+ output "$::prefix/etc/ppp/ioptions",
+ "lock
+usepeerdns
+defaultroute
+";
+
+ network::tools::write_secret_backend($isdn->{login}, $isdn->{passwd});
+
+ 1;
+}
+
+sub write_capi_conf {
+ my ($capi_card) = @_;
+ my $capi_conf;
+ my $firmware = $capi_card->{firmware} || '-';
+ if ($capi_card->{driver} eq "fcclassic") {
+ $capi_conf = "fcclassic - - 0x300 5 - -\n# adjust IRQ and IO !! ^^^^^ ^^^\n";
+ } elsif ($capi_card->{driver} eq "fcpnp") {
+ $capi_conf = "fcpnp - - 0x300 5 - -\n# adjust IRQ and IO !! ^^^^^ ^^^\n";
+ } else {
+ $capi_conf = "$capi_card->{driver} $firmware - - - - -\n";
+ }
+
+ output("$::prefix/etc/capi.conf", $capi_conf);
+}
+
+sub unload_connection {
+ my ($isdn) = @_;
+ require services;
+ services::stop("isdn4linux"); #- to be stopped before capi is loaded
+ if ($isdn->{driver} eq "capidrv") {
+ #- stop capi4linux before new config is written so that it can unload the driver
+ services::stop("capi4linux");
+ }
+}
+
+sub install_packages {
+ my ($isdn, $in) = @_;
+
+ $in->do_pkgs->install(
+ 'isdn4k-utils',
+ $isdn->{driver} eq "capidrv" ?
+ (if_(!modules::module_is_available($isdn->{driver}), @{$isdn->{packages}}),
+ if_($isdn->{firmware} && ! -f "$::prefix/usr/lib/isdn/$isdn->{firmware}", "$isdn->{driver}-firmware"))
+ :
+ ('isdn4net', if_($isdn->{speed} =~ /128/, 'ibod'))
+ );
+}
+
+sub prepare_connection {
+ my ($isdn) = @_;
+ if ($isdn->{driver} eq "capidrv") {
+ services::enable('capi4linux');
+ } else {
+ services::disable('capi4linux');
+ }
+ services::enable('isdn4linux');
+}
+
+sub read_config {
+ my ($isdn) = @_;
+
+ my %match = (I4L_USERNAME => 'login',
+ I4L_LOCALMSN => 'phone_in',
+ I4L_REMOTE_OUT => 'phone_out',
+ I4L_DIALMODE => 'dialing_mode',
+ I4L_IDLETIME => 'huptimeout',
+ I4L_MODULE => 'driver',
+ I4L_TYPE => 'type',
+ I4L_IRQ => 'irq',
+ I4L_MEMBASE => 'mem',
+ I4L_PORT => 'io',
+ I4L_IO0 => 'io0',
+ I4L_IO1 => 'io1',
+ I4L_FIRMWARE => 'firmware');
+ foreach ('link/myisp', 'card/mycard') {
+ my %conf = getVarsFromSh("$::prefix/etc/isdn/profile/$_");
+ foreach (keys %conf) {
+ $isdn->{$match{$_}} = $conf{$_} if $match{$_} && $conf{$_};
+ }
+ }
+
+ $isdn->{passwd} = network::tools::passwd_by_login($isdn->{login});
+}
+
+my $file = "$ENV{SHARE_PATH}/ldetect-lst/isdn.db";
+$file = "$::prefix$file" if !-e $file;
+
+sub get_info_providers_backend {
+ my ($isdn, $name) = @_;
+ $name eq N("Unlisted - edit manually") and return;
+ foreach (catMaybeCompressed($file)) {
+ chop;
+ my ($name_, $phone, $real, $dns1, $dns2) = split '=>';
+ if ($name eq $name_) {
+ @$isdn{qw(user_name phone_out DOMAINNAME2 dnsServer3 dnsServer2)} =
+ ((split(/\|/, $name_))[2], $phone, $real, $dns1, $dns2);
+ }
+ }
+}
+
+sub read_providers_backend() { map { /(.*?)=>/ } catMaybeCompressed($file) }
+
+
+sub detect_backend {
+ my ($modules_conf) = @_;
+ my @isdn;
+ require detect_devices;
+ each_index {
+ my $c = $_;
+ my $isdn = { map { $_ => $c->{$_} } qw(description vendor id driver card_type type) };
+ $isdn->{intf_id} = $::i;
+ $isdn->{$_} = sprintf("%0x", $isdn->{$_}) foreach 'vendor', 'id';
+ $isdn->{card_type} = $c->{bus} eq 'USB' ? 'usb' : 'pci';
+ $isdn->{description} =~ s/.*\|//;
+# $c->{options} !~ /id=HiSax/ && $isdn->{driver} eq "hisax" and $c->{options} .= " id=HiSax";
+ if ($c->{options} !~ /protocol=/ && $isdn->{protocol} =~ /\d/) {
+ $modules_conf->set_options($c->{driver}, $c->{options} . " protocol=" . $isdn->{protocol});
+ }
+ $c->{options} =~ /protocol=(\d)/ and $isdn->{protocol} = $1;
+ push @isdn, $isdn;
+ } detect_devices::probe_category('network/isdn');
+ \@isdn;
+}
+
+sub get_cards_by_type {
+ my ($isdn_type) = @_;
+ grep { $_->{card} eq $isdn_type } @isdndata;
+}
+
+
+sub get_cards() {
+ my %buses = (
+ isa => N("ISA / PCMCIA") . "/" . N("I do not know"),
+ pci => N("PCI"),
+ usb => N("USB"),
+ );
+ # pmcia alias (we should really split up pcmcia from isa in isdn db):
+ $buses{pcmcia} = $buses{isa};
+
+ map { $buses{$_->{card}} . "|" . $_->{description} => $_ } @isdndata;
+}
+
+
+sub find_capi_card {
+ my ($isdn) = @_;
+ find {
+ hex($isdn->{vendor}) == $_->{vendor} && hex($isdn->{id}) == $_->{id};
+ } @isdn_capi;
+}
+
+sub get_capi_card {
+ my ($in, $isdn) = @_;
+
+ my $capi_card = find_capi_card($isdn) or return;
+
+ #- check if the capi driver is available
+ unless (modules::module_is_available($capi_card->{driver}) || ($capi_card->{packages} = $in->do_pkgs->check_kernel_module_packages($capi_card->{driver}))) {
+ log::explanations("a capi driver ($capi_card->{driver}) exists to replace $isdn->{driver}, but it is not installed and no packages provide it");
+ return;
+ }
+
+ $capi_card;
+}
+
+1;
diff --git a/lib/network/connection/isdn/consts.pm b/lib/network/connection/isdn/consts.pm
new file mode 100644
index 0000000..a53ddbe
--- /dev/null
+++ b/lib/network/connection/isdn/consts.pm
@@ -0,0 +1,460 @@
+package network::connection::isdn::consts; # $Id: consts.pm 54070 2006-08-07 17:34:38Z blino $
+use vars qw(@ISA @EXPORT);
+@ISA = qw(Exporter);
+@EXPORT = qw(@isdndata @isdn_capi);
+
+our @isdndata =
+ (
+ { description => "Teles|16.0", #1 irq, mem, io
+ driver => 'hisax',
+ type => '1',
+ irq => '5',
+ mem => '0xd000',
+ io => '0xd80',
+ card => 'isa',
+ },
+ { description => "Teles|8.0", #2 irq, mem
+ driver => 'hisax',
+ type => '2',
+ irq => '9',
+ mem => '0xd800',
+ card => 'isa',
+ },
+ { description => "Teles|16.3 (ISA non PnP)", #3 irq, io
+ driver => 'hisax',
+ type => '3',
+ irq => '9',
+ io => '0xd80',
+ card => 'isa',
+ },
+ { description => "Teles|16.3c (ISA PnP)", #14 irq, io
+ driver => 'hisax',
+ type => '14',
+ irq => '9',
+ io => '0xd80',
+ card => 'isa',
+ },
+ { description => "Creatix/Teles|Generic (ISA PnP)", #4 irq, io0 (ISAC), io1 (HSCX)
+ driver => 'hisax',
+ type => '4',
+ irq => '5',
+ io0 => '0x0000',
+ io1 => '0x0000',
+ card => 'isa',
+ },
+ { description => "Teles|generic", #21 no parameter
+ driver => 'hisax',
+ type => '21',
+ card => 'pci',
+ },
+ { description => "Teles|16.3 (PCMCIA)", #8 irq, io
+ driver => 'hisax',
+ type => '8',
+ irq => '',
+ io => '0x',
+ card => 'isa',
+ },
+ { description => "Teles|S0Box", #25 irq, io (of the used lpt port)
+ driver => 'hisax',
+ type => '25',
+ irq => '7',
+ io => '0x378',
+ card => 'isa',
+ },
+ { description => "ELSA|PCC/PCF cards", #6 io or nothing for autodetect (the io is required only if you have n>1 ELSA|card)
+ driver => 'hisax',
+ type => '6',
+ io => "",
+ card => 'isa',
+ },
+ { description => "ELSA|Quickstep 1000", #7 irq, io (from isapnp setup)
+ driver => 'hisax',
+ type => '7',
+ irq => '5',
+ io => '0x300',
+ card => 'isa',
+ },
+ { description => "ELSA|Quickstep 1000", #18 no parameter
+ driver => 'hisax',
+ type => '18',
+ card => 'pci',
+ },
+ { description => "ELSA|Quickstep 3000", #18 no parameter
+ driver => 'hisax',
+ type => '18',
+ card => 'pci',
+ },
+ { description => "ELSA|generic (PCMCIA)", #10 irq, io (set with card manager)
+ driver => 'hisax',
+ type => '10',
+ irq => '',
+ io => '0x',
+ card => 'isa',
+ },
+ { description => "ELSA|MicroLink (PCMCIA)", #10 irq, io (set with card manager)
+ driver => 'elsa_cs',
+ card => 'isa',
+ },
+ { description => "ITK|ix1-micro Rev.2", #9 irq, io
+ driver => 'hisax',
+ type => '9',
+ irq => '9',
+ io => '0xd80',
+ card => 'isa',
+ },
+ { description => "Eicon.Diehl|Diva (ISA PnP)", #11 irq, io
+ driver => 'hisax',
+ type => '11',
+ irq => '9',
+ io => '0x180',
+ card => 'isa',
+ },
+ { description => "Eicon.Diehl|Diva 20", #11 no parameter
+ driver => 'hisax',
+ type => '11',
+ card => 'pci',
+ },
+ { description => "Eicon.Diehl|Diva 20PRO", #11 no parameter
+ driver => 'hisax',
+ type => '11',
+ card => 'pci',
+ },
+ { description => "Eicon.Diehl|Diva 20_U", #11 no parameter
+ driver => 'hisax',
+ type => '11',
+ card => 'pci',
+ },
+ { description => "Eicon.Diehl|Diva 20PRO_U", #11 no parameter
+ driver => 'hisax',
+ type => '11',
+ card => 'pci',
+ },
+ { description => "ASUS|COM ISDNLink", #12 irq, io (from isapnp setup)
+ driver => 'hisax',
+ type => '12',
+ irq => '5',
+ io => '0x200',
+ card => 'isa',
+ },
+ { description => "ASUS|COM ISDNLink",
+ driver => 'hisax',
+ type => '35',
+ card => 'pci',
+ },
+ { description => "DynaLink|Any",
+ driver => 'hisax',
+ type => '12',
+ card => 'pci',
+ },
+ { description => "DynaLink|IS64PH, ASUSCOM", #36
+ driver => 'hisax',
+ type => '36',
+ card => 'pci',
+ },
+ { description => "HFC|2BS0 based cards", #13 irq, io
+ driver => 'hisax',
+ type => '13',
+ irq => '9',
+ io => '0xd80',
+ card => 'isa',
+ },
+ { description => "HFC|2BDS0", #35 none
+ driver => 'hisax',
+ type => '35',
+ card => 'pci',
+ },
+ { description => "HFC|2BDS0 S+, SP (PCMCIA)", #37 irq,io (pcmcia must be set with cardmgr)
+ driver => 'hisax',
+ type => '37',
+ card => 'isa',
+ },
+ { description => "Sedlbauer|Speed Card", #15 irq, io
+ driver => 'hisax',
+ type => '15',
+ irq => '9',
+ io => '0xd80',
+ card => 'isa',
+ },
+ { description => "Sedlbauer|PC/104", #15 irq, io
+ driver => 'hisax',
+ type => '15',
+ irq => '9',
+ io => '0xd80',
+ card => 'isa',
+ },
+ { description => "Sedlbauer|Speed Card", #15 no parameter
+ driver => 'hisax',
+ type => '15',
+ card => 'pci',
+ },
+ { description => "Sedlbauer|Speed Star (PCMCIA)", #22 irq, io (set with card manager)
+ driver => 'sedlbauer_cs',
+ card => 'isa',
+ },
+ { description => "Sedlbauer|Speed Fax+ (ISA Pnp)", #28 irq, io (from isapnp setup)
+ driver => 'hisax',
+ type => '28',
+ irq => '9',
+ io => '0xd80',
+ card => 'isa',
+ firmware => '/usr/lib/isdn/ISAR.BIN',
+ },
+ { description => "Sedlbauer|Speed Fax+", #28 no parameter
+ driver => 'hisax',
+ type => '28',
+ card => 'pci',
+ firmware => '/usr/lib/isdn/ISAR.BIN',
+ },
+ { description => "USR|Sportster internal", #16 irq, io
+ driver => 'hisax',
+ type => '16',
+ irq => '9',
+ io => '0xd80',
+ card => 'isa',
+ },
+ { description => "Generic|MIC card", #17 irq, io
+ driver => 'hisax',
+ type => '17',
+ irq => '9',
+ io => '0xd80',
+ card => 'isa',
+ },
+ { description => "Compaq|ISDN S0 card", #19 irq, io0, io1, io (from isapnp setup io=IO2)
+ driver => 'hisax',
+ type => '19',
+ irq => '5',
+ io => '0x0000',
+ io0 => '0x0000',
+ io1 => '0x0000',
+ card => 'isa',
+ },
+ { description => "Generic|NETjet card", #20 no parameter
+ driver => 'hisax',
+ type => '20',
+ card => 'pci',
+ },
+ { description => "Dr. Neuhaus|Niccy (ISA PnP)", #24 irq, io0, io1 (from isapnp setup)
+ driver => 'hisax',
+ type => '24',
+ irq => '5',
+ io0 => '0x0000',
+ io1 => '0x0000',
+ card => 'isa',
+ },
+ { description => "Dr. Neuhaus|Niccy", ##24 no parameter
+ driver => 'hisax',
+ type => '24',
+ card => 'pci',
+ },
+ { description => "AVM|A1 (Fritz) (ISA non PnP)", #5 irq, io
+ driver => 'hisax',
+ type => '5',
+ irq => '10',
+ io => '0x300',
+ card => 'isa',
+ },
+ { description => "AVM|ISA Pnp generic", #27 irq, io (from isapnp setup)
+ driver => 'hisax',
+ type => '27',
+ irq => '5',
+ io => '0x300',
+ card => 'isa',
+ },
+ { description => "AVM|A1 (Fritz) (PCMCIA)", #26 irq, io (set with card manager)
+ driver => 'hisax',
+ type => '26',
+ irq => '',
+ card => 'isa',
+ },
+ { description => "AVM|PCI (Fritz!)", #27 no parameter
+ driver => 'hisax',
+ type => '27',
+ card => 'pci',
+ },
+ { description => "AVM|B1",
+ driver => 'b1pci',
+ card => 'pci',
+ },
+ { description => "Siemens|I-Surf 1.0 (ISA Pnp)", #29 irq, io, memory (from isapnp setup)
+ driver => 'hisax',
+ type => '29',
+ irq => '9',
+ io => '0xd80',
+ mem => '0xd000',
+ card => 'isa',
+ },
+ { description => "ACER|P10 (ISA Pnp)", #30 irq, io (from isapnp setup)
+ driver => 'hisax',
+ type => '30',
+ irq => '5',
+ io => '0x300',
+ card => 'isa',
+ },
+ { description => "HST|Saphir (ISA Pnp)", #31 irq, io
+ driver => 'hisax',
+ type => '31',
+ irq => '5',
+ io => '0x300',
+ card => 'isa',
+ },
+ { description => "Telekom|A4T", #32 none
+ driver => 'hisax',
+ type => '32',
+ card => 'pci',
+ },
+ { description => "Scitel|Quadro", #33 subcontroller (4*S0, subctrl 1...4)
+ driver => 'hisax',
+ type => '33',
+ card => 'pci',
+ },
+ { description => "Gazel|ISDN cards", #34 irq,io
+ driver => 'hisax',
+ type => '34',
+ irq => '5',
+ io => '0x300',
+ card => 'isa',
+ },
+ { description => "Gazel|Gazel ISDN cards", #34 none
+ driver => 'hisax',
+ type => '34',
+ card => 'pci',
+ },
+ { description => "Winbond|W6692 and Winbond based cards", #36 none
+ driver => 'hisax',
+ type => '36',
+ card => 'pci',
+ },
+ { description => "BeWAN|R834",
+ driver => 'hisax_st5481',
+ type => '99',
+ card => 'usb',
+ },
+ { description => "Gazel|128",
+ driver => 'hisax_st5481',
+ type => '99',
+ card => 'usb',
+ },
+ );
+
+#- cards than can be used with capi drivers
+our @isdn_capi =
+ (
+ {
+ vendor => 0x1131,
+ id => 0x5402,
+ description => 'AVM Audiovisuelles|Fritz DSL ISDN/DSL Adapter',
+ bus => 'PCI',
+ driver => 'fcdsl',
+ firmware => 'fdslbase.bin'
+ },
+ {
+ vendor => 0x1244,
+ id => 0x0a00,
+ description => 'AVM Audiovisuelles|A1 ISDN Adapter [Fritz] CAPI',
+ bus => 'PCI',
+ driver => 'fcpci'
+ },
+ {
+ vendor => 0x1244,
+ id => 0x0e00,
+ description => 'AVM Audiovisuelles|A1 ISDN Adapter [Fritz] CAPI',
+ bus => 'PCI',
+ driver => 'fcpci'
+ },
+ {
+ vendor => 0x1244,
+ id => 0x0f00,
+ description => 'AVM Audiovisuelles|Fritz DSL ISDN/DSL Adapter',
+ bus => 'PCI',
+ driver => 'fcdsl',
+ firmware => 'fdslbase.bin'
+ },
+ {
+ vendor => 0x1244,
+ id => 0x2700,
+ description => 'AVM Audiovisuelles|Fritz!Card DSL SL',
+ bus => 'PCI',
+ driver => 'fcdslsl',
+ firmware => 'fdssbase.bin'
+ },
+ {
+ vendor => 0x1244,
+ id => 0x2900,
+ description => 'AVM Audiovisuelles|Fritz DSL Ver. 2.0',
+ bus => 'PCI',
+ driver => 'fcdsl2',
+ firmware => 'fds2base.bin'
+ },
+ {
+ vendor => 0x057c,
+ id => 0x0c00,
+ description => 'AVM GmbH|FritzCard USB ISDN TA',
+ bus => 'USB',
+ driver => 'fcusb'
+ },
+ {
+ vendor => 0x057c,
+ id => 0x1000,
+ description => 'AVM GmbH|FritzCard USB 2 Ver. 2.0 ISDN TA',
+ bus => 'USB',
+ driver => 'fcusb2',
+ firmware => 'fus2base.frm'
+ },
+ {
+ vendor => 0x057c,
+ id => 0x1900,
+ description => 'AVM GmbH|FritzCard USB 2 Ver. 3.0 ISDN TA',
+ bus => 'USB',
+ driver => 'fcusb2',
+ firmware => 'fus3base.frm'
+ },
+ {
+ vendor => 0x057c,
+ id => 0x2000,
+ description => 'AVM GmbH|Fritz X USB ISDN TA',
+ bus => 'USB',
+ driver => 'fxusb'
+ },
+ {
+ vendor => 0x057c,
+ id => 0x2300,
+ description => 'AVM GmbH|FtitzCard USB DSL ISDN TA/ DSL Modem',
+ bus => 'USB',
+ driver => 'fcdslusb',
+ firmware => 'fdsubase.frm'
+ },
+ {
+ vendor => 0x057c,
+ id => 0x2800,
+ description => 'AVM GmbH|Fritz X USB OEM ISDN TA',
+ bus => 'USB',
+ driver => 'fxusb_CZ'
+ },
+ {
+ vendor => 0x057c,
+ id => 0x3000,
+ description => 'AVM GmbH|FtitzCard USB DSL SL USB',
+ bus => 'USB',
+ driver => 'fcdslusba',
+ firmware => 'fdlabase.frm'
+ },
+ {
+ vendor => 0x057c,
+ id => 0x3500,
+ description => 'AVM GmbH|FtitzCard USB DSL SL USB Analog',
+ bus => 'USB',
+ driver => 'fcdslslusb',
+ firmware => 'fdlubase.frm',
+ },
+ {
+ vendor => 0x057c,
+ id => 0x3600,
+ description => 'AVM FRITZ!Card DSL USB v2.0',
+ bus => 'USB',
+ driver => 'fcdslusb2',
+ firmware => 'fds2base.frm',
+ },
+ );
+
+
+1;
diff --git a/lib/network/connection/pots.pm b/lib/network/connection/pots.pm
new file mode 100644
index 0000000..22299f6
--- /dev/null
+++ b/lib/network/connection/pots.pm
@@ -0,0 +1,133 @@
+package network::connection::pots;
+
+use base qw(network::connection::ppp);
+
+use strict;
+use common;
+
+sub get_type_name {
+ #-PO: POTS means "Plain old telephone service"
+ N("POTS");
+}
+sub get_type_description {
+ #-PO: POTS means "Plain old telephone service"
+ #-PO: remove it if it doesn't have an equivalent in your language
+ #-PO: for example, in French, it can be translated as "RTC"
+ N("Analog telephone modem (POTS)");
+}
+sub _get_type_icon { 'potsmodem' }
+sub get_metric { 50 }
+
+sub handles_ifcfg {
+ my ($_class, $ifcfg) = @_;
+ $ifcfg->{DEVICE} =~ /^ppp/ && exists $ifcfg->{MODEMPORT};
+}
+
+sub get_devices {
+ require detect_devices;
+ require modules;
+ #- FIXME: module alias should be written when config is written only
+ #detect_devices::getModem(modules::any_conf->read);
+ ();
+}
+
+my @thirdparty_settings = (
+ {
+ matching => qr/^Hcf:/,
+ description => 'HCF 56k Modem',
+ url => 'http://www.linuxant.com/drivers/hcf/',
+ name => 'hcfpcimodem',
+ kernel_module => {
+ test_file => 'hcfpciengine',
+ },
+ tools => {
+ test_file => '/usr/sbin/hcfpciconfig',
+ },
+ device => '/dev/ttySHCF0',
+ post => '/usr/sbin/hcfpciconfig --auto',
+ restart_service => 'hcfpci',
+ },
+
+ {
+ matching => qr/^Hsf:/,
+ description => 'HSF 56k Modem',
+ url => 'http://www.linuxant.com/drivers/hsf/',
+ name => 'hsfmodem',
+ kernel_module => {
+ test_file => 'hsfengine',
+ },
+ tools => {
+ test_file => '/usr/sbin/hsfconfig',
+ },
+ device => '/dev/ttySHSF0',
+ post => '/usr/sbin/hsfconfig --auto',
+ restart_service => 'hsf',
+ },
+
+ {
+ matching => qr/^LT:/,
+ description => 'LT WinModem',
+ url => 'http://www.heby.de/ltmodem/',
+ name => 'ltmodem',
+ kernel_module => 1,
+ tools => {
+ test_file => '/etc/devfs/conf.d/ltmodem.conf',
+ },
+ device => '/dev/ttyS14',
+ links => [
+ 'http://linmodems.technion.ac.il/Ltmodem.html',
+ 'http://linmodems.technion.ac.il/packages/ltmodem/',
+ ],
+ },
+
+ {
+ matching => [ list_modules::category2modules('network/slmodem') ],
+ description => 'Smartlink WinModem',
+ url => 'http://linmodems.technion.ac.il/resources.html#smartlink',
+ name => 'slmodem',
+ kernel_module => 1,
+ tools => {
+ test_file => '/usr/sbin/slmodemd',
+ },
+ device => '/dev/ttySL0',
+ post => sub {
+ my ($driver) = @_;
+ addVarsInSh("$::prefix/etc/sysconfig/slmodemd", { SLMODEMD_MODULE => $driver });
+ },
+ restart_service => "slmodemd",
+ },
+
+ {
+ name => 'sm56',
+ description => 'Motorola SM56 WinModem',
+ url => 'http://www.motorola.com/softmodem/driver.htm#linux',
+ kernel_module => {
+ package => 'sm56',
+ },
+ no_distro_package => 1,
+ device => '/dev/sm56',
+ },
+);
+
+sub get_thirdparty_settings { \@thirdparty_settings }
+
+sub get_providers {
+ my $db_path = "/usr/share/apps/kppp/Provider";
+ #$in->do_pkgs->ensure_is_installed('kdenetwork-kppp-provider', $db_path);
+ my $separator = "|";
+ my %providers;
+ foreach (all($::prefix . $db_path)) {
+ s!_! !g;
+ my $country = $_;
+ my $t_country = translate($country);
+ my $country_root = $::prefix . $db_path . '/' . $country;
+ foreach (grep { $_ ne '.directory' } all($country_root)) {
+ my $path = $country_root . $_;
+ s/%([0-9]{3})/chr(int($1))/eg;
+ $providers{$t_country . $separator . $_} = { path => $path };
+ }
+ }
+ (\%providers, $separator);
+}
+
+1;
diff --git a/lib/network/connection/ppp.pm b/lib/network/connection/ppp.pm
new file mode 100644
index 0000000..37fabb3
--- /dev/null
+++ b/lib/network/connection/ppp.pm
@@ -0,0 +1,150 @@
+package network::connection::ppp;
+
+use strict;
+use common;
+
+use base qw(network::connection);
+
+my %authentication_methods = (
+ script => N_("Script-based"),
+ pap => N_("PAP"),
+ terminal_ => N_("Terminal-based"),
+ chap => N_("CHAP"),
+ pap_chap => N_("PAP/CHAP"),
+);
+
+my @kppp_authentication_methods = qw(script pap terminal chap pap_chap);
+my @secrets_files = qw(pap-secrets chap-secrets);
+
+sub get_access_settings {
+ my ($self) = @_;
+ [
+ { label => N("Account Login (user name)"), val => \$self->{access}{login} },
+ { label => N("Account Password"), val => \$self->{access}{password}, hidden => 1 },
+ ];
+}
+
+sub get_secret {
+ my ($_self, $login) = @_;
+ foreach (@secrets_files) {
+ my $file = "$::prefix/etc/ppp/$_";
+ foreach (cat_($file)) {
+ my ($l, undef, $password) = split(' ');
+ if ($l && $password) {
+ s/^(['"]?)(.*)\1$/$2/ foreach $l, $password;
+ return $password if $l eq $login;
+ }
+ }
+ }
+}
+
+sub write_secrets {
+ my ($self) = @_;
+ foreach (@secrets_files) {
+ my $file = "$::prefix/etc/ppp/$_";
+ substInFile {
+ s/^'$self->{access}{login}'.*\n//;
+ $_ .= "\n'$self->{access}{login}' * '$self->{access}{password}' * \n" if eof;
+ } $file;
+ chmod 0600, $file;
+ }
+}
+
+sub get_options {
+ #- options: PAPNAME PEERDNS
+}
+
+sub get_tty_device { "/dev/modem" }
+
+sub get_up_timeout { 20 }
+
+sub build_ifcfg_settings {
+ my ($self) = @_;
+ my $modemport = $self->get_tty_device;
+ my $settings = put_in_hash($self->{settings}, {
+ if_($modemport, MODEMPORT => $modemport),
+ LINESPEED => "115200",
+ PERSIST => "yes",
+ DEFROUTE => "yes",
+ #- FIXME: move in network::connection::cellular or network::connection::cellular_card
+ if_($self->get_interface !~ /^hso/, DEBUG => "yes"),
+ if_($self->{access}{cid}, CELLULAR_CID => $self->{access}{cid}),
+ });
+ $self->SUPER::build_ifcfg_settings($settings);
+}
+
+sub build_chat {
+ my ($self) = @_;
+ #- optional:
+ #- auth_method: key of %authentication_methods
+ #- dial_number
+ #- login
+ #- password
+ #- at_commands: array ref of AT commands
+ (map { "ABORT $_" } "BUSY", "ERROR", "'NO CARRIER'", "'NO DIALTONE'", "'Invalid Login'", "'Login incorrect'", "VOICE", "'NO ANSWER'", "DELAYED", "'SIM PIN'"),
+ qq('' ATZ),
+ if_(ref $self->{access}{at_commands}, map { qq(OK-AT-OK '$_') } @{$self->{access}{at_commands}}),
+ if_($self->{access}{dial_number},
+ qq(OK 'ATDT$self->{access}{dial_number}'),
+ qq(TIMEOUT 120),
+ qq(CONNECT ''),
+ if_(member($self->{access}{auth_method}, qw(script terminal)),
+ qq('ogin:--ogin:' '$self->{access}{login}'),
+ qq('ord:' '$self->{access}{password}')),
+ qq(TIMEOUT 5),
+ qq('~--' ''),
+ );
+}
+
+sub get_chat_file {
+ my ($self) = @_;
+ "/etc/sysconfig/network-scripts/chat-" . $self->get_interface;
+}
+
+sub write_chat {
+ my ($self) = @_;
+ output_with_perm($::prefix . $self->get_chat_file, 0755, join("\n", $self->build_chat, ''));
+}
+
+sub get_peer_default_options {
+ my ($_self) = @_;
+ qw(noauth defaultroute usepeerdns);
+}
+
+sub build_peer {
+ my ($self) = @_;
+ #- options:
+ #- init
+ #- connect
+ #- pty
+ #- plugin
+ if ($self->{access}{use_chat}) {
+ my $chat_file = $self->get_chat_file;
+ $self->{access}{peer}{connect} ||= qq("/usr/sbin/chat -v -f $chat_file");
+ }
+ $self->get_peer_default_options,
+ (map { if_($self->{access}{peer}{$_}, $_ . " " . $self->{access}{peer}{$_}) } qw(init connect pty plugin)),
+ if_($self->{access}{login}, qq(user "$self->{access}{login}"));
+}
+
+sub write_peer {
+ my ($self) = @_;
+ my $interface = $self->get_interface;
+ my $peer_file = "/etc/ppp/peers/$interface";
+ output_with_perm($::prefix . $peer_file, 0755, join("\n", $self->build_peer, ''));
+}
+
+sub write_ppp_settings {
+ my ($self) = @_;
+ $self->write_secrets if $self->{access}{login};
+ $self->write_chat if $self->{access}{use_chat};
+ $self->write_peer;
+}
+
+sub write_settings {
+ my ($self) = @_;
+ $self->write_ppp_settings;
+ $self->network::connection::write_settings;
+}
+
+1;
diff --git a/lib/network/connection/providers/cellular.pm b/lib/network/connection/providers/cellular.pm
new file mode 100644
index 0000000..79f757c
--- /dev/null
+++ b/lib/network/connection/providers/cellular.pm
@@ -0,0 +1,183 @@
+package network::connection::providers::cellular;
+
+use common;
+use utf8;
+
+# http://www.reqwireless.com/apns.html
+# http://wiki.mig33.com/mig33/show/apn
+# http://www.unlocks.co.uk/gprs_settings.php
+# http://www.opera.com/products/smartphone/docs/connect/
+# http://www.taniwha.org.uk/gprs.html
+# https://rip.psg.com/~randy/gprs-ppp.html
+# http://computer.cocus.co.il/Setup/V3X/MPT/Addons/GPRSope.inf
+
+our %data = (
+ N("Brazil") . "|Vivo" => {
+ apn => "zap.vivo.com.br",
+ login => "vivo",
+ password => "vivo",
+ },
+ N("Estonia") . "|Bravocom" => {
+ apn => "internet",
+ },
+ N("Estonia") . "|Elisa" => {
+ apn => "internet",
+ },
+ N("Estonia") . "|EMT" => {
+ apn => "internet.emt.ee",
+ },
+ N("Estonia") . "|Simpel/POP!" => {
+ apn => "internet2.emt.ee",
+ },
+ N("Estonia") . "|Tele2" => {
+ apn => "internet.tele2.ee",
+ },
+ N("Estonia") . "|TeleYks" => {
+ apn => "internet",
+ },
+ N("Estonia") . "|Zorro" => {
+ apn => "internet",
+ },
+ # http://www.cubio.fi/fi/cubio_gsm/mms_ja_gprs_asetukset
+ N("Finland") . "|Cubio" => {
+ apn => "internet.cubio.net",
+ },
+ # http://www.dnaoy.fi/Yksityisille/Matkaviestinta/Asiakaspalvelu/Documents/Ohjeet/asetukset_yleiset_wxp.pdf
+ N("Finland") . "|DNA" => {
+ apn => "internet",
+ },
+ # http://matkaviestinta.elisa.fi/public/elisa.do?id=hen_liit_palvelut_gprs,ds_muut_0054.htm
+ # http://tuki.elisa.fi/asiakastuki/elisa.do?id=hen_as_matkaviest_ohjeet,as_help_page_0025.htm
+ # Official pages have inconsistent information on whether login and
+ # password are used. Presumably they are ignored, but we set them just to
+ # be sure.
+ N("Finland") . "|Elisa" => {
+ apn => "internet",
+ login => "rlnet",
+ password => "internet",
+ },
+ # http://koti.mbnet.fi/simopot/asetukset/index.php?operaattori=globetel
+ N("Finland") . "|Globetel" => {
+ apn => "internet",
+ },
+ # http://www.kolumbus.com/asiakaspalvelu_asetukset.html
+ # Redirects to Elisa automatic setup, presumably same settings apply.
+ N("Finland") . "|Kolumbus" => {
+ apn => "internet",
+ login => "rlnet",
+ password => "internet",
+ },
+ # http://saunalahti.fi/tuki/gsm/vo/ohjeemail.php
+ N("Finland") . "|Saunalahti" => {
+ apn => "internet.saunalahti",
+ },
+ # http://koti.mbnet.fi/simopot/asetukset/index.php?operaattori=sonera
+ N("Finland") . "|Sonera" => {
+ apn => "internet",
+ },
+ # http://tdc.fi/publish.php?dogtag=songfi_at_ojl_int
+ N("Finland") . "|Song" => {
+ apn => "internet.song.fi",
+ login => "song@internet",
+ password => "songnet",
+ },
+ # http://www.tele.fi/Asiakaspalvelu/Ohjeet/K%E4nnyk%E4ll%E4+nettiin+ja+tiedonsiirto/Asetukset/
+ N("Finland") . "|Tele Finland" => {
+ apn => "internet",
+ },
+ # http://www.gsm.aland.fi/tjanster/wap/wap.htm
+ N("Finland") . "|Ålands Mobiltelefon" => {
+ apn => "internet",
+ },
+ N("France") . "|BouygTel" => {
+ apn => "ebouygtel.com",
+ },
+ N("France") . "|BouygTel Pro" => {
+ apn => "a2bouygtel.com",
+ login => "a2b",
+ password => "acces",
+ },
+ N("France") . "|BouygTel Pro GPRS" => {
+ apn => "b2bouygtel.com",
+ login => "B2B",
+ password => "NET",
+ },
+ N("France") . "|Orange Web" => {
+ apn => "orange.fr",
+ login => "orange",
+ password => "orange",
+ },
+ # http://www.actua-mobiles.com/p800/viewtopic.php?p=12184#12184
+ # http://www.planete-se.net/index.php?showtopic=18184&st=0&p=186768&#entry186768
+ N("France") . "|Orange WAP" => {
+ apn => "orange",
+ login => "orange",
+ password => "orange",
+ },
+ N("France") . "|Orange Entreprises" => {
+ apn => "internet-entreprise",
+ login => "orange",
+ password => "orange",
+ },
+ N("France") . "|SFR EeePC (Clé Internet 3G+)" => {
+ apn => "slsfr",
+ },
+ N("France") . "|SFR WAP (Illimythics / Pass Surf)" => {
+ apn => "wapsfr",
+ },
+ N("France") . "|SFR Web (Clé Internet / Data)" => {
+ apn => "websfr",
+ },
+ N("Germany") . "|Vodafone Live! WAP" => {
+ apn => "wap.vodafone.de",
+ },
+ N("Germany") . "|Vodafone Web" => {
+ apn => "web.vodafone.de",
+ },
+ N("Italy") . "|TIM" => {
+ apn => "ibox.tim.it",
+ login => "tim",
+ password => "tim",
+ },
+ N("Italy") . "|Vodafone" => {
+ apn => "web.omnitel.it",
+ login => "vodafone",
+ password => "vodafone",
+ },
+ N("Italy") . "|Wind" => {
+ apn => "internet.wind.it",
+ login => "wind",
+ password => "wind",
+ },
+ N("Italy") . "|Tre" => {
+ apn => "tre.it",
+ login => "tre",
+ password => "tre",
+ },
+ N("Poland") . "|Era GSM" => {
+ apn => "erainternet",
+ login => "erainternet",
+ password => "erainternet",
+ },
+ N("Poland") . "|Orange" => {
+ apn => "internet",
+ login => "internet",
+ password => "internet",
+ },
+ N("Poland") . "|Play" => {
+ apn => "INTERNET",
+ },
+ N("Poland") . "|Plus GSM" => {
+ apn => "internet",
+ },
+ N("United Kingdom") . "|O2" => {
+ apn => "mobile.o2.co.uk",
+ login => "mobileweb",
+ password => "password",
+ },
+ N("United States") . "|Cingular" => {
+ apn => "isp.cingular",
+ },
+);
+
+1;
diff --git a/lib/network/connection/providers/cellular_extra.pm b/lib/network/connection/providers/cellular_extra.pm
new file mode 100644
index 0000000..4039afa
--- /dev/null
+++ b/lib/network/connection/providers/cellular_extra.pm
@@ -0,0 +1,2284 @@
+package network::connection::providers::cellular_extra;
+
+use common;
+use utf8;
+
+# this list was imported from mobile-broadband-provider-info
+# (http://svn.gnome.org/svn/mobile-broadband-provider-info/trunk) and converted
+# to perl data using some black magick
+
+our %data = (
+ N("United Arab Emirates") . "|Etisalat" => {
+ apn => "mnet",
+ login => "mnet",
+ password => "mnet",
+ dns => "194.170.1.6",
+ dns => "194.170.1.7",
+ },
+ N("United Arab Emirates") . "|Etisalat 3G" => {
+ apn => "etisalat.ae",
+ login => "etisalat.ae",
+ password => "etisalat.ae",
+ },
+ N("Albania") . "|Vodafone" => {
+ apn => "Twa",
+ },
+ N("Angola") . "|Movinet" => {
+ cdma => 1,
+ login => "uname",
+ },
+ N("Argentina") . "|Personal" => {
+ apn => "gprs.personal.com",
+ login => "gprs",
+ password => "adgj",
+ dns => "172.25.7.6",
+ dns => "172.25.7.7",
+ },
+ N("Argentina") . "|CTI" => {
+ apn => "internet.ctimovil.com.ar",
+ login => "ctigprs",
+ dns => "170.51.255.100",
+ dns => "170.51.242.18",
+ },
+ N("Argentina") . "|Movistar" => {
+ apn => "internet.gprs.unifon.com.ar",
+ login => "wap",
+ password => "wap",
+ },
+ N("Angola") . "|Unitel" => {
+ apn => "internet.unitel.co.ao",
+ },
+ N("Austria") . "|Max Max Online Mobil" => {
+ apn => "gprsinternet",
+ login => "GPRS",
+ dns => "213.162.64.1",
+ dns => "213.162.64.2",
+ },
+ N("Austria") . "|Max Online" => {
+ apn => "gprsinternet",
+ login => "GPRS",
+ dns => "213.162.64.1",
+ dns => "213.162.64.2",
+ },
+ N("Austria") . "|Max Online (Business)" => {
+ apn => "business.gprsinternet",
+ login => "GPRS",
+ dns => "213.162.64.1",
+ dns => "213.162.64.2",
+ },
+ N("Austria") . "|Max Online (Metro)" => {
+ apn => "gprsmetro",
+ login => "GPRS",
+ dns => "213.162.64.1",
+ dns => "213.162.64.2",
+ },
+ N("Austria") . "|Mobilkom/A1" => {
+ apn => "a1.net",
+ login => "ppp@a1plus.at",
+ password => "ppp",
+ dns => "194.48.139.254",
+ dns => "194.48.124.202",
+ },
+ N("Austria") . "|Orange" => {
+ apn => "web.one.at",
+ login => "web",
+ password => "web",
+ dns => "194.24.128.100",
+ dns => "194.24.128.102",
+ },
+ N("Austria") . "|Tele.ring" => {
+ apn => "web",
+ login => "web@telering.at",
+ password => "web",
+ dns => "212.95.31.167 ",
+ dns => "212.95.31.168",
+ },
+ N("Austria") . "|Telering" => {
+ apn => "web",
+ login => "web@telering.at",
+ password => "web",
+ dns => "212.95.31.167 ",
+ dns => "212.95.31.168",
+ },
+ N("Austria") . "|Drei" => {
+ apn => "drei.at",
+ },
+ N("Austria") . "|Yesss" => {
+ apn => "web.yesss.at",
+ },
+ N("Australia") . "|Exetel" => {
+ apn => "exetel1",
+ },
+ N("Australia") . "|Optus" => {
+ apn => "internet",
+ dns => "202.139.83.3",
+ dns => "192.65.91.129",
+ },
+ N("Australia") . "|Optus 3G" => {
+ apn => "CONNECT",
+ dns => "202.139.83.3",
+ dns => "192.65.91.129",
+ },
+ N("Australia") . "|Telstra" => {
+ apn => "telstra.wap",
+ dns => "139.130.4.4",
+ dns => "203.50.2.71",
+ },
+ N("Australia") . "|Telstra (3G data pack)" => {
+ apn => "telstra.datapack",
+ password => "Telstra",
+ dns => "139.130.4.4",
+ dns => "203.50.2.71",
+ },
+ N("Australia") . "|Telstra (UMTS/HSDPA)" => {
+ apn => "telstra.internet",
+ dns => "139.130.4.4",
+ dns => "203.50.170.2",
+ },
+ N("Australia") . "|Telstra (3G PC pack - pay by time)" => {
+ apn => "telstra.pcpack",
+ password => "Telstra",
+ dns => "139.130.4.4",
+ dns => "203.50.2.71",
+ },
+ N("Australia") . "|Telstra (Next G card)" => {
+ dns => "139.130.4.4",
+ dns => "203.50.2.71",
+ },
+ N("Australia") . "|Three" => {
+ apn => "3netaccess",
+ login => "a",
+ password => "a",
+ dns => "202.124.68.130",
+ dns => "202.124.76.66",
+ },
+ N("Australia") . "|Three Prepaid" => {
+ apn => "3services",
+ login => "a",
+ password => "a",
+ dns => "202.124.68.130",
+ dns => "202.124.76.66",
+ },
+ N("Australia") . "|Virgin Mobile" => {
+ apn => "VirginInternet",
+ login => "guest",
+ password => "guest",
+ dns => "61.88.88.88",
+ },
+ N("Australia") . "|Vodafone" => {
+ apn => "vfinternet.au",
+ dns => "192.189.54.33",
+ dns => "210.80.58.3",
+ },
+ N("Azerbaijan") . "|Azercell" => {
+ apn => "internet",
+ },
+ N("Azerbaijan") . "|Bakcell" => {
+ apn => "mms",
+ },
+ N("Bosnia and Herzegovina") . "|BH GSM" => {
+ apn => "mms.bhmobile.ba",
+ },
+ N("Bahamas") . "|Batelco" => {
+ apn => "internet.btcbahamas.com",
+ },
+ N("Bangladesh") . "|AKTel" => {
+ apn => "atmmms",
+ dns => "192.168.023.007",
+ },
+ N("Bangladesh") . "|Banglalink" => {
+ apn => "blweb",
+ },
+ N("Bangladesh") . "|Grameen Phone" => {
+ apn => "gpinternet",
+ dns => "202.56.4.120",
+ dns => "202.56.4.121",
+ },
+ N("Barbados") . "|Digicel" => {
+ apn => "isp.digicelbarbados.com",
+ },
+ N("Belgium") . "|Mobistar (business)" => {
+ apn => "web.pro.be",
+ login => "mobistar",
+ password => "mobistar",
+ dns => "212.65.63.10",
+ dns => "212.65.63.145",
+ },
+ N("Belgium") . "|Orange" => {
+ apn => "orangeinternet",
+ },
+ N("Belgium") . "|Proximus Inter" => {
+ apn => "internet.proximus.be",
+ dns => "195.238.2.21",
+ dns => "195.238.2.22",
+ },
+ N("Belgium") . "|Proximus Intra" => {
+ apn => "intraprox.be",
+ dns => "195.238.2.21",
+ dns => "195.238.2.22",
+ },
+ N("Belgium") . "|Base" => {
+ apn => "gprs.base.be",
+ login => "base",
+ password => "base",
+ },
+ N("Belgium") . "|Mobistar (personal)" => {
+ apn => "internet.be",
+ login => "mobistar",
+ password => "mobistar",
+ dns => "212.65.63.10",
+ dns => "212.65.63.145",
+ },
+ N("Bulgaria") . "|GloBul" => {
+ apn => "internet.globul.bg",
+ login => "globul",
+ dns => "192.168.88.11",
+ },
+ N("Bulgaria") . "|M-Tel" => {
+ apn => "inet-gprs.mtel.bg",
+ login => "mtel",
+ password => "mtel",
+ dns => "213.226.7.34",
+ dns => "213.226.7.35",
+ },
+ N("Bulgaria") . "|GloBul" => {
+ apn => "internet.globul.bg",
+ login => "globul",
+ password => "[none]",
+ dns => "192.168.88.11",
+ },
+ N("Brazil") . "|Claro" => {
+ apn => "claro.com.br",
+ login => "claro",
+ password => "claro",
+ },
+ N("Brazil") . "|Oi" => {
+ apn => "gprs.oi.com.br",
+ password => "oioioi",
+ },
+ N("Brazil") . "|TIM" => {
+ apn => "tim.br",
+ login => "tim",
+ password => "tim",
+ dns => "10.223.246.102",
+ dns => "10.223.246.103",
+ },
+ N("Brazil") . "|Oi (WAP)" => {
+ apn => "wapgprs.oi.com.br",
+ login => "oiwap",
+ password => "oioioi",
+ },
+ N("Brazil") . "|Velox" => {
+ apn => "wap.telcel.com",
+ login => "iesgprs",
+ password => "iesgprs2002",
+ dns => "66.36.250.14",
+ },
+ N("Brazil") . "|Vivo" => {
+ apn => "zap.vivo.com.br",
+ login => "vivo",
+ password => "vivo",
+ },
+ N("Belarus") . "|VELCOM" => {
+ apn => "wap.velcom.by",
+ login => "wap",
+ password => "wap",
+ },
+ N("Belarus") . "|VELCOM (Simple GPRS)" => {
+ apn => "web.velcom.by",
+ login => "web",
+ password => "web",
+ dns => "212.98.162.154",
+ dns => "193.232.248.2",
+ },
+ N("Belarus") . "|VELCOM (Web Plus)" => {
+ apn => "plus.velcom.by",
+ login => "plus",
+ password => "plus",
+ },
+ N("Belarus") . "|VELCOM (Privet)" => {
+ apn => "privet.velcom.by",
+ login => "privet",
+ password => "privet",
+ },
+ N("Belarus") . "|MTS" => {
+ apn => "internet.mts.by",
+ login => "mts",
+ password => "mts",
+ },
+ N("Botswana") . "|Mascom Wireless" => {
+ apn => "internet.mascom",
+ },
+ N("Canada") . "|Microcell Fido" => {
+ apn => "internet.fido.ca",
+ login => "fido",
+ password => "fido",
+ dns => "204.92.15.211",
+ dns => "207.181.101.4",
+ },
+ N("Canada") . "|Rogers AT&T" => {
+ apn => "internet.com",
+ login => "wapuser1",
+ password => "wap",
+ dns => "207.181.101.4",
+ dns => "207.181.101.5",
+ },
+ N("Congo (Kinshasa)") . "|Vodafone" => {
+ apn => "vodanet",
+ login => "vodalive",
+ dns => "172.24.97.1",
+ },
+ N("Congo (Brazzaville)") . "|Vodafone" => {
+ apn => "vodanet",
+ login => "vodalive",
+ dns => "172.24.97.1",
+ },
+ N("Switzerland") . "|Orange" => {
+ apn => "mobileoffice3g",
+ dns => "213.55.128.1 ",
+ dns => "213.55.128.2",
+ },
+ N("Switzerland") . "|Sunrise" => {
+ apn => "internet",
+ login => "internet",
+ password => "internet",
+ dns => "212.35.35.35",
+ dns => "212.35.35.5",
+ },
+ N("Switzerland") . "|Swisscom" => {
+ apn => "gprs.swisscom.ch",
+ login => "gprs",
+ password => "gprs",
+ dns => "164.128.36.34",
+ dns => "164.128.76.39",
+ },
+ N("Cote d'Ivoire") . "|internet" => {
+ apn => "172.16.100.5",
+ },
+ N("Chile") . "|Claro Chile" => {
+ apn => "bam.clarochile.cl",
+ login => "clarochile",
+ password => "clarochile",
+ },
+ N("Chile") . "|Claro Chile - Prepago" => {
+ apn => "bap.clarochile.cl",
+ login => "clarochile",
+ password => "clarochile",
+ },
+ N("Chile") . "|Claro Chile - WAP" => {
+ apn => "wap.clarochile.cl",
+ login => "clarochile",
+ password => "clarochile",
+ },
+ N("Chile") . "|Entel PCS" => {
+ apn => "imovil.entelpcs.cl",
+ login => "entelpcs",
+ password => "entelpcs",
+ },
+ N("Chile") . "|Entel PCS - WAP" => {
+ apn => "bam.entelpcs.cl",
+ login => "entelpcs",
+ password => "entelpcs",
+ },
+ N("Chile") . "|Movistar" => {
+ apn => "web.tmovil.cl",
+ login => "web",
+ password => "web",
+ },
+ N("Chile") . "|Movistar - WAP" => {
+ apn => "wap.tmovil.cl",
+ login => "wap",
+ password => "wap",
+ },
+ N("Cameroon") . "|Orange" => {
+ apn => "orangecmgprs",
+ login => "orange",
+ password => "orange",
+ },
+ N("Cameroon") . "|MTN" => {
+ apn => "INTERNET",
+ dns => "-",
+ },
+ N("China") . "|China Mobile" => {
+ apn => "cmnet",
+ dns => "211.136.20.203 ",
+ dns => "211.136.20.203",
+ },
+ N("China") . "|China Unicom" => {
+ apn => "none",
+ dns => "211.136.20.203 ",
+ dns => "211.136.20.203",
+ },
+ N("Costa Rica") . "|IceCelular" => {
+ apn => "icecelular",
+ dns => "208.133.206.44 ",
+ dns => "208.133.206.44",
+ },
+ N("Colombia") . "|Comcel" => {
+ apn => "internet.comcel.com.co",
+ login => "COMCELWEB",
+ password => "COMCELWEB",
+ },
+ N("Colombia") . "|Tigo" => {
+ apn => "web.colombiamovil.com.co",
+ },
+ N("Colombia") . "|Movistar" => {
+ apn => "internet.movistar.com.co",
+ login => "movistar",
+ password => "movistar",
+ },
+ N("Czech Republic") . "|Cesky Mobil (postpaid)" => {
+ apn => "internet",
+ dns => "212.67.64.2",
+ dns => "217.77.161.131",
+ },
+ N("Czech Republic") . "|Cesky Mobil (prepaid)" => {
+ apn => "Cinternet",
+ dns => "212.67.64.2",
+ dns => "217.77.161.131",
+ },
+ N("Czech Republic") . "|EuroTel (Go)" => {
+ apn => "gointernet",
+ dns => "160.218.10.200 ",
+ dns => "160.218.43.200",
+ },
+ N("Czech Republic") . "|Oscar (Post p.)" => {
+ apn => "internet",
+ login => "wap",
+ password => "wap",
+ dns => "217.77.161.130",
+ dns => "217.77.161.131",
+ },
+ N("Czech Republic") . "|Oscar (Pre p.)" => {
+ apn => "internet",
+ dns => "217.77.161.130",
+ dns => "217.77.161.131",
+ },
+ N("Czech Republic") . "|Paegas Internet" => {
+ apn => "internet.click.cz",
+ dns => "62.141.0.1",
+ dns => "62.141.0.2",
+ },
+ N("Czech Republic") . "|Paegas Profil" => {
+ apn => "profil.click.cz",
+ dns => "62.141.0.1",
+ dns => "62.141.0.2",
+ },
+ N("Czech Republic") . "|Radiomibil" => {
+ apn => "internet.click.cz",
+ },
+ N("Czech Republic") . "|T-Mobil" => {
+ apn => "internet.t-mobile.cz",
+ dns => "62.141.0.1",
+ dns => "213.162.65.1",
+ },
+ N("Czech Republic") . "|Eurotel (contract)" => {
+ apn => "internet",
+ dns => "160.218.10.200",
+ dns => "160.218.43.200",
+ },
+ N("Czech Republic") . "|Eurotel (contract - open)" => {
+ apn => "internet.open",
+ dns => "160.218.10.200 ",
+ dns => "160.218.43.200",
+ },
+ N("Czech Republic") . "|Vodafone (contract)" => {
+ apn => "internet",
+ dns => "217.77.161.130",
+ dns => "217.77.161.131",
+ },
+ N("Czech Republic") . "|Telefonica (contract)" => {
+ apn => "internet",
+ dns => "160.218.10.200",
+ dns => "160.218.43.200",
+ },
+ N("Czech Republic") . "|Vodafone (pre-pay)" => {
+ apn => "ointernet",
+ dns => "217.77.161.130",
+ dns => "217.77.161.131",
+ },
+ N("Czech Republic") . "|Telefonica (Go)" => {
+ apn => "gointernet",
+ dns => "160.218.10.201",
+ dns => "194.228.2.1",
+ },
+ N("Germany") . "|AldiTalk/MedionMobile" => {
+ apn => "internet.eplus.de",
+ login => "eplus",
+ password => "gprs",
+ dns => "212.23.97.2",
+ dns => "212.23.97.3",
+ },
+ N("Germany") . "|E-Plus (pre-pay)" => {
+ apn => "internet.eplus.de",
+ login => "eplus",
+ password => "gprs",
+ dns => "212.23.97.2",
+ dns => "212.23.97.3",
+ },
+ N("Germany") . "|E-Plus (contract)" => {
+ apn => "internet.eplus.de",
+ login => "eplus",
+ password => "gprs",
+ dns => "212.23.97.2",
+ dns => "212.23.97.3",
+ },
+ N("Germany") . "|o2 (pay-by-MB)" => {
+ apn => "internet",
+ dns => "195.182.110.132 ",
+ dns => "62.134.11.4",
+ },
+ N("Germany") . "|o2 (pay-by-time)" => {
+ apn => "surfo2",
+ dns => "195.182.110.132 ",
+ dns => "62.134.11.4",
+ },
+ N("Germany") . "|o2 Viag Interkom" => {
+ apn => "internet",
+ dns => "195.182.110.132",
+ dns => "62.134.11.4",
+ },
+ N("Germany") . "|T-mobile (D1)" => {
+ apn => "internet.t-d1.de",
+ password => "t-d1",
+ dns => "193.254.160.1 ",
+ dns => "193.254.160.130",
+ },
+ N("Germany") . "|Vodafone (D2)" => {
+ apn => "web.vodafone.de",
+ login => "vodafone",
+ password => "vodafone",
+ dns => "139.7.30.125",
+ dns => "139.7.30.126",
+ },
+ N("Germany") . "|Vodafone (D2) WebSessions" => {
+ apn => "event.vodafone.de",
+ login => "vodafone",
+ password => "vodafone",
+ dns => "139.7.30.125",
+ dns => "139.7.30.126",
+ },
+ N("Germany") . "|FONIC" => {
+ apn => "pinternet.interkom.de",
+ },
+ N("Denmark") . "|3 (Bredbånd)" => {
+ apn => "bredband.tre.dk",
+ },
+ N("Denmark") . "|3 (Bredbånd Premium Kontant)" => {
+ apn => "net.tre.dk",
+ },
+ N("Denmark") . "|3 (Mobil Abonnement)" => {
+ apn => "data.tre.dk",
+ },
+ N("Denmark") . "|OiSTER" => {
+ apn => "bredband.oister.dk",
+ },
+ N("Denmark") . "|ice.net (Nordisk Mobiltelefon)" => {
+ cdma => 1,
+ login => "cdma",
+ password => "cdma",
+ },
+ N("Denmark") . "|Sonofon" => {
+ apn => "internet",
+ dns => "212.88.64.199",
+ dns => "212.88.64.14",
+ },
+ N("Denmark") . "|TDC" => {
+ apn => "internet",
+ dns => "194.239.134.83",
+ dns => "193.162.153.164",
+ },
+ N("Denmark") . "|Fullrate" => {
+ apn => "internet",
+ login => "Fullrate",
+ password => "Fullrate",
+ },
+ N("Denmark") . "|Telia" => {
+ apn => "www.internet.mtelia.dk",
+ },
+ N("Denmark") . "|BiBoB" => {
+ apn => "internet.bibob.dk",
+ },
+ N("Dominican Republic") . "|Orange" => {
+ apn => "orangenet.com.do",
+ },
+ N("Ecuador") . "|Porta 3G" => {
+ apn => "internet.porta.com.ec",
+ },
+ N("Estonia") . "|EMT" => {
+ apn => "internet.emt.ee",
+ dns => "217.71.32.116",
+ dns => "217.71.32.115",
+ },
+ N("Estonia") . "|Nordea" => {
+ apn => "internet.emt.ee",
+ },
+ N("Estonia") . "|Radiolinja" => {
+ apn => "internet",
+ dns => "194.204.0.1",
+ },
+ N("Estonia") . "|RLE" => {
+ apn => "internet",
+ },
+ N("Estonia") . "|Tele2" => {
+ apn => "internet.tele2.ee",
+ login => "wap",
+ password => "wap",
+ },
+ N("Egypt") . "|Click Vodafone" => {
+ apn => "internet.vodafone.net",
+ login => "internet",
+ password => "internet",
+ },
+ N("Egypt") . "|Etisalat" => {
+ apn => "etisalat",
+ },
+ N("Egypt") . "|MobiNil" => {
+ apn => "mobinilweb",
+ dns => "80.75.166.250",
+ dns => "163.121.163.201",
+ },
+ N("Spain") . "|Amena" => {
+ apn => "internet",
+ login => "CLIENTE",
+ password => "AMENA",
+ dns => "213.143.32.20 ",
+ dns => "213.143.33.8",
+ },
+ N("Spain") . "|Orange" => {
+ apn => "internet",
+ login => "CLIENTE",
+ password => "AMENA",
+ dns => "213.143.32.20 ",
+ dns => "213.143.33.8",
+ },
+ N("Spain") . "|Simyo" => {
+ apn => "gprs-service.com",
+ },
+ N("Spain") . "|Telefonica" => {
+ apn => "movistar.es",
+ login => "movistar",
+ password => "movistar",
+ dns => "194.179.1.100",
+ dns => "194.179.1.101",
+ },
+ N("Spain") . "|Vodafone (Airtel)" => {
+ apn => "airtelnet.es",
+ login => "vodafone",
+ password => "vodafone",
+ dns => "212.73.32.3",
+ dns => "212.73.32.67",
+ },
+ N("Spain") . "|Vodafone" => {
+ apn => "airtelnet.es",
+ login => "vodafone",
+ password => "vodafone",
+ dns => "196.207.32.69",
+ dns => "196.43.45.190",
+ },
+ N("Spain") . "|Yoigo" => {
+ apn => "Internet",
+ },
+ N("Spain") . "|Jazztel" => {
+ apn => "jazzinternet",
+ },
+ N("Finland") . "|Dna" => {
+ apn => "internet",
+ dns => "217.78.192.22 ",
+ dns => "217.78.192.78",
+ },
+ N("Finland") . "|Elisa" => {
+ apn => "internet",
+ },
+ N("Finland") . "|Saunalahti" => {
+ apn => "internet.saunalahti",
+ },
+ N("Finland") . "|Sonera" => {
+ apn => "internet",
+ dns => "192.89.123.230",
+ dns => "192.89.123.231",
+ },
+ N("Finland") . "|Sonera prointernet" => {
+ apn => "prointernet",
+ dns => "192.89.123.230",
+ dns => "192.89.123.231",
+ },
+ N("Fiji") . "|Vodafone" => {
+ apn => "vfinternet.fj",
+ },
+ N("France") . "|Bouygues Telecom (B2Bouygtel)" => {
+ apn => "b2bouygtel.com",
+ dns => "62.201.129.99",
+ },
+ N("France") . "|Bouygues Telecom" => {
+ apn => "ebouygtel.com",
+ dns => "62.201.129.99",
+ dns => "62.201.159.99",
+ },
+ N("France") . "|France Telecom" => {
+ apn => "orange.fr.mnc001.mcc208.gprs",
+ login => "gprs",
+ },
+ N("France") . "|Orange (contract)" => {
+ apn => "orange.fr",
+ login => "orange",
+ password => "orange",
+ dns => "194.51.3.56",
+ dns => "194.51.3.76",
+ },
+ N("France") . "|Orange (business contract)" => {
+ apn => "internet-entreprise",
+ login => "orange",
+ password => "orange",
+ },
+ N("France") . "|Orange (no contact)" => {
+ apn => "orange",
+ login => "orange",
+ password => "orange",
+ dns => "194.51.3.56 ",
+ dns => "194.51.3.76",
+ },
+ N("France") . "|Orange MIB" => {
+ apn => "orange-mib",
+ login => "mportail",
+ password => "mib",
+ dns => "172.17.0.2 ",
+ dns => "172.17.0.4",
+ },
+ N("France") . "|Orange Mobicarte" => {
+ apn => "orange",
+ login => "orange",
+ password => "orange",
+ },
+ N("France") . "|Orange Internet Everywhere 3G" => {
+ apn => "orange.ie",
+ },
+ N("France") . "|SFR" => {
+ apn => "websfr",
+ dns => "172.20.2.10",
+ dns => "172.20.2.39",
+ },
+ N("France") . "|Transatel Telecom" => {
+ apn => "netgprs.com",
+ },
+ N("France") . "|TEN" => {
+ apn => "ao.fr",
+ login => "orange",
+ password => "orange",
+ },
+ N("France") . "|TEN (pay-by-MB)" => {
+ apn => "ofnew.fr",
+ login => "orange",
+ password => "orange",
+ },
+ N("France") . "|Orange (business)" => {
+ apn => "internet-entreprise",
+ login => "orange",
+ password => "orange",
+ dns => "194.51.3.56",
+ dns => "194.51.3.76",
+ },
+ N("France") . "|Orange (contract)" => {
+ apn => "orange.fr",
+ login => "orange",
+ password => "orange",
+ dns => "194.51.3.56",
+ dns => "194.51.3.76",
+ },
+ N("United Kingdom") . "|airtel vodaphone" => {
+ apn => "airtel-ci-gprs.com",
+ },
+ N("United Kingdom") . "|Jersey Telecom" => {
+ apn => "pepper",
+ login => "abc",
+ password => "abc",
+ dns => "212.9.0.135",
+ dns => "212.9.0.136",
+ },
+ N("United Kingdom") . "|o2 (contract)" => {
+ apn => "mobile.o2.co.uk",
+ login => "o2web",
+ password => "password",
+ dns => "193.113.200.200",
+ dns => "193.113.200.201",
+ },
+ N("United Kingdom") . "|o2 (pre-pay)" => {
+ apn => "payandgo.o2.co.uk",
+ login => "payandgo",
+ password => "payandgo",
+ },
+ N("United Kingdom") . "|Orange (contract)" => {
+ apn => "orangeinternet",
+ login => "orange",
+ password => "orange",
+ dns => "193.35.133.10 ",
+ dns => "193.35.134.10",
+ },
+ N("United Kingdom") . "|Orange JustTalk" => {
+ apn => "orangeinternet",
+ dns => "193.35.133.10",
+ dns => "193.35.134.10",
+ },
+ N("United Kingdom") . "|T-Mobile" => {
+ apn => "general.t-mobile.uk",
+ login => "User",
+ password => "mms",
+ dns => "149.254.201.126",
+ dns => "149.254.192.126",
+ },
+ N("United Kingdom") . "|Virgin Mobile" => {
+ apn => "vdata",
+ dns => "196.7.0.138",
+ dns => "196.7.142.132",
+ },
+ N("United Kingdom") . "|Vodafone (contract)" => {
+ apn => "internet",
+ login => "web",
+ password => "web",
+ dns => "10.206.65.68",
+ dns => "10.203.65.68",
+ },
+ N("United Kingdom") . "|Vodafone (pre-pay)" => {
+ apn => "pp.vodafone.co.uk",
+ login => "wap",
+ password => "wap",
+ dns => "172.29.1.11 ",
+ dns => "172.29.1.11",
+ },
+ N("United Kingdom") . "|Vodafone (TopUp and Go)" => {
+ apn => "pp.internet",
+ },
+ N("United Kingdom") . "|o2 (contract-faster)" => {
+ apn => "mobile.o2.co.uk",
+ login => "faster",
+ password => "password",
+ dns => "193.113.200.200",
+ dns => "193.113.200.201",
+ },
+ N("United Kingdom") . "|3" => {
+ apn => "3internet",
+ },
+ N("United Kingdom") . "|3 (handsets)" => {
+ apn => "three.co.uk",
+ },
+ N("United Kingdom") . "|Orange (Pay and Go)" => {
+ apn => "orangewap",
+ login => "Multimedia",
+ password => "Orange",
+ dns => "158.43.192.1",
+ dns => "158.43.128.1",
+ },
+ N("United Kingdom") . "|Orange (Pay Monthly)" => {
+ apn => "orangeinternet",
+ login => "orange",
+ password => "multimedia",
+ dns => "158.43.192.1",
+ dns => "158.43.128.1",
+ },
+ N("Georgia") . "|Geocell" => {
+ apn => "Internet",
+ dns => "212.72.130.20",
+ dns => "212.72.152.001",
+ },
+ N("Ghana") . "|Areeba" => {
+ apn => "internet.areeba.com.gh",
+ dns => "196.201.34.5",
+ dns => "213.137.131.3",
+ },
+ N("Ghana") . "|ONETouch" => {
+ apn => "browse",
+ },
+ N("Ghana") . "|Tigo" => {
+ apn => "web.tigo.com.gh",
+ login => "web",
+ password => 1,
+ },
+ N("Ghana") . "|Zain" => {
+ apn => "internet",
+ },
+ N("Greece") . "|Cosmote" => {
+ apn => "3g-internet",
+ dns => "195.167.65.194",
+ },
+ N("Greece") . "|Telestet" => {
+ apn => "gnet.b-online.gr",
+ password => "24680",
+ dns => "212.152.79.19",
+ dns => "212.152.79.20",
+ },
+ N("Greece") . "|Vodafone" => {
+ apn => "internet",
+ },
+ N("Greece") . "|TIM" => {
+ apn => "gint.b-online.gr",
+ login => "web",
+ password => "web",
+ },
+ N("Guatemala") . "|Comcel" => {
+ apn => "Wap.tigo.gt",
+ login => "Wap",
+ password => "Wap",
+ },
+ N("Guatemala") . "|PCS Digital" => {
+ apn => "ideasalo",
+ },
+ N("Guyana") . "|GT&T Cellink Plus" => {
+ apn => "wap.cellinkgy.com",
+ login => "test",
+ password => "test",
+ },
+ N("Hong Kong") . "|CSL" => {
+ apn => "internet",
+ dns => "202.84.255.1",
+ dns => "203.116.254.150",
+ },
+ N("Hong Kong") . "|New World" => {
+ apn => "internet",
+ },
+ N("Hong Kong") . "|People" => {
+ apn => "internet",
+ },
+ N("Hong Kong") . "|SmarTone" => {
+ apn => "internet",
+ dns => "202.140.96.51",
+ dns => "202.140.96.52",
+ },
+ N("Hong Kong") . "|Sunday" => {
+ apn => "internet",
+ },
+ N("Hong Kong") . "|Orange" => {
+ apn => "web.orangehk.com",
+ },
+ N("Hong Kong") . "|Three" => {
+ apn => "mobile.three.com.hk",
+ },
+ N("Honduras") . "|Tigo" => {
+ apn => "internet.tigo.hn",
+ },
+ N("Croatia") . "|HTmobile" => {
+ apn => "www.htgprs.hr",
+ dns => "10.12.0.1",
+ },
+ N("Croatia") . "|VIPNET" => {
+ apn => "gprs5.vipnet.hr",
+ login => "38591",
+ password => "38591",
+ dns => "195.29.159.15",
+ },
+ N("Croatia") . "|VIPNET" => {
+ apn => "gprs0.vipnet.hr",
+ login => "38591",
+ password => "38591",
+ dns => "195.29.159.15",
+ },
+ N("Croatia") . "|VIPNET" => {
+ apn => "3g.vip.hr",
+ login => "38591",
+ password => "38591",
+ dns => "212.91.97.3 ",
+ dns => "212.91.97.4",
+ },
+ N("Hungary") . "|Pannon (átalánydíjas)" => {
+ apn => "netx",
+ dns => "193.225.155.254 ",
+ dns => "194.149.0.157",
+ },
+ N("Hungary") . "|Pannon (normál)" => {
+ apn => "net",
+ dns => "193.225.153.17",
+ dns => "195.56.172.113",
+ },
+ N("Hungary") . "|T-Mobile" => {
+ apn => "internet",
+ dns => "212.51.115.1 ",
+ dns => "194.176.224.6",
+ },
+ N("Hungary") . "|Pannon (tömörített)" => {
+ apn => "snet",
+ dns => "193.225.153.17",
+ dns => "194.149.0.157",
+ },
+ N("Hungary") . "|T-Mobile (mms)" => {
+ apn => "mms-westel",
+ login => "mms",
+ dns => "212.51.115.1",
+ dns => "194.176.224.3",
+ },
+ N("Hungary") . "|Vodafone (előf. norm.)" => {
+ apn => "standardnet.vodafone.net",
+ login => "vodawap",
+ password => "vodawap",
+ dns => "80.244.97.30",
+ dns => "80.244.96.1",
+ },
+ N("Hungary") . "|Vodafone (előf. töm.)" => {
+ apn => "internet.vodafone.net",
+ login => "vodawap",
+ password => "vodawap",
+ dns => "80.244.97.30",
+ dns => "80.244.96.1",
+ },
+ N("Hungary") . "|Vodafone (felt. norm.)" => {
+ apn => "vitamax.snet.vodafone.net",
+ dns => "80.244.97.30",
+ dns => "80.244.96.1",
+ },
+ N("Hungary") . "|Vodafone (felt. töm.)" => {
+ apn => "vitamax.internet.vodafone.net",
+ dns => "80.244.97.30",
+ dns => "80.244.96.1",
+ },
+ N("Indonesia") . "|AXIS" => {
+ apn => "AXIS",
+ login => "axis",
+ password => "123456",
+ },
+ N("Indonesia") . "|IM3" => {
+ apn => "www.imdosat-m3.net",
+ login => "gprs",
+ password => "im3",
+ dns => "202.155.46.66 ",
+ dns => "202.155.46.77",
+ },
+ N("Indonesia") . "|Indosat" => {
+ apn => "satelindogprs.com",
+ dns => "202.152.162.250",
+ },
+ N("Indonesia") . "|Telkomsel" => {
+ apn => "internet",
+ login => "wap",
+ password => "wap123",
+ dns => "202.152.0.2",
+ dns => "202.155.14.251",
+ },
+ N("Indonesia") . "|Excelcomindo (XL)" => {
+ apn => "www.xlgprs.net",
+ login => "xlgprs",
+ password => "proxl",
+ dns => "202.152.254.245",
+ dns => "202.152.254.246",
+ },
+ N("Indonesia") . "|Indosat (Matrix)" => {
+ apn => "satelindogprs.com indosatgprs",
+ dns => "202.155.46.66",
+ dns => "202.155.46.77",
+ },
+ N("Ireland") . "|o2 (contract)" => {
+ apn => "open.internet",
+ login => "gprs",
+ password => "gprs",
+ dns => "62.40.32.33",
+ dns => "62.40.32.34",
+ },
+ N("Ireland") . "|o2 (pre-pay)" => {
+ apn => "pp.internet",
+ login => "faster",
+ password => "web",
+ dns => "62.40.32.33",
+ dns => "62.40.32.34",
+ },
+ N("Ireland") . "|Vodafone (HSDPA/GPRS/EDGE/UMTS)" => {
+ apn => "hs.vodafone.ie",
+ login => "vodafone",
+ password => "vodafone",
+ },
+ N("Ireland") . "|Vodafone (GPRS/EDGE/UMTS) (old)" => {
+ apn => "isp.vodafone.ie",
+ login => "vodafone",
+ password => "vodafone",
+ },
+ N("Ireland") . "|Meteor" => {
+ apn => "isp.mymeteor.ie",
+ login => "my",
+ password => "meteor",
+ },
+ N("Ireland") . "|Vodafone (pre-pay)" => {
+ apn => "live.vodafone.com",
+ login => "vodafone",
+ password => "vodafone",
+ dns => "10.24.59.100",
+ },
+ N("Ireland") . "|Three Ireland" => {
+ apn => "3ireland.ie",
+ dns => "172.31.140.69",
+ dns => "172.30.140.69",
+ },
+ N("Israel") . "|CellCom" => {
+ apn => "etecsa",
+ login => "etecsa",
+ dns => "192.168.91.10",
+ dns => "192.168.91.4",
+ },
+ N("Israel") . "|Orange" => {
+ apn => "orangeinternet",
+ dns => "158.43.192.1",
+ dns => "158.43.128.1",
+ },
+ N("Israel") . "|Vodafone (MTC)" => {
+ apn => "apn01",
+ dns => "10.10.10.30",
+ },
+ N("India") . "|Airtel" => {
+ apn => "airtelgprs.com",
+ dns => "202.56.230.5 ",
+ dns => "202.56.240.5",
+ },
+ N("India") . "|BPL" => {
+ apn => "bplgprs.com",
+ login => "bplmobile",
+ dns => "202.169.145.34",
+ dns => "202.169.129.40",
+ },
+ N("India") . "|BSNL" => {
+ apn => "celloneportal",
+ dns => "192.168.051.163",
+ },
+ N("India") . "|BSNL Prepaid (West Bengal)" => {
+ apn => "www.e.pr",
+ dns => "218.248.240.208",
+ dns => "218.248.240.135",
+ },
+ N("India") . "|Hutch (normal)" => {
+ apn => "www",
+ dns => "10.11.206.51",
+ dns => "10.11.206.50",
+ },
+ N("India") . "|Hutch (Gujarat)" => {
+ apn => "web",
+ dns => "10.11.206.51",
+ dns => "10.11.206.50",
+ },
+ N("India") . "|Idea Cellular" => {
+ apn => "internet",
+ dns => "10.4.42.15",
+ },
+ N("India") . "|MTNL Delhi" => {
+ apn => "gprsmtnldel",
+ login => "mtnl",
+ password => "mtnl123",
+ },
+ N("India") . "|MTNL Mumbai (pre-paid)" => {
+ apn => "gprsppsmum",
+ login => "mtnl",
+ password => "mtnl123",
+ },
+ N("India") . "|MTNL Mumbai (post-paid)" => {
+ apn => "gprsmtnlmum",
+ login => "mtnl",
+ password => "mtnl123",
+ },
+ N("India") . "|MTNL Mumbai (Plan 2)" => {
+ apn => "gprsmtnlmum",
+ login => "mtnl",
+ password => "mtnl123",
+ },
+ N("India") . "|Orange" => {
+ apn => "portalnmms",
+ dns => "10.11.206.51",
+ dns => "10.11.206.50",
+ },
+ N("India") . "|Spice telecom" => {
+ apn => "Simplyenjoy",
+ login => "Mobile number",
+ password => "spice",
+ },
+ N("India") . "|Spice telecom (kar)" => {
+ apn => "simplydownload",
+ },
+ N("India") . "|Tata Indicom (Plug2Surf)" => {
+ cdma => 1,
+ login => "internet",
+ password => "internet",
+ },
+ N("India") . "|Telekomsel" => {
+ apn => "internet",
+ login => "wap",
+ password => "wap123",
+ },
+ N("India") . "|Vodafone" => {
+ apn => "www",
+ login => "guest",
+ password => "guest",
+ },
+ N("Iceland") . "|Islandssimi" => {
+ apn => "gprs.islandssimi.is",
+ dns => "213.176.128.51",
+ dns => "213.176.128.50",
+ },
+ N("Iceland") . "|Nova" => {
+ apn => "internet.nova.is",
+ dns => "192.168.190.54",
+ dns => "192.168.190.55",
+ },
+ N("Italy") . "|Vodafone" => {
+ apn => "web.omnitel.it",
+ },
+ N("Italy") . "|TIM" => {
+ apn => "ibox.tim.it",
+ },
+ N("Italy") . "|TIM (WAP)" => {
+ apn => "wap.tim.it",
+ login => "WAPTIM",
+ dns => "213.230.155.94 ",
+ dns => "213.230.130.222",
+ },
+ N("Italy") . "|Wind" => {
+ apn => "internet.wind",
+ },
+ N("Italy") . "|Wind (business)" => {
+ apn => "internet.wind.biz",
+ },
+ N("Italy") . "|3 (ricaricabile)" => {
+ apn => "tre.it",
+ },
+ N("Italy") . "|3 (abbonamento)" => {
+ apn => "datacard.tre.it",
+ },
+ N("Italy") . "|Fastweb (SIM voce/dati)" => {
+ apn => "apn.fastweb.it",
+ },
+ N("Italy") . "|Fastweb (SIM solo dati)" => {
+ apn => "datacard.fastweb.it",
+ },
+ N("Jamaica") . "|Cable & Wireless" => {
+ apn => "wap",
+ },
+ N("Jamaica") . "|Digicel" => {
+ apn => "web.digiceljamaica.com",
+ login => "wapuser",
+ password => "wap03jam",
+ dns => "208.131.176.126",
+ dns => "200.10.152.232",
+ },
+ N("Japan") . "|Vodafone (J-Phone)" => {
+ apn => "vodafone",
+ login => "ai@vodafone",
+ password => "vodafone",
+ dns => "61.195.195.153",
+ dns => "61.195.194.26",
+ },
+ N("Japan") . "|Softbank Mobile" => {
+ cdma => 1,
+ login => "ai@softbank",
+ password => "softbank",
+ },
+ N("Japan") . "|e-mobile" => {
+ cdma => 1,
+ login => "em",
+ password => "em",
+ },
+ N("Japan") . "|NTTdocomo" => {
+ cdma => 1,
+ },
+ N("Japan") . "|au(KDDI)" => {
+ cdma => 1,
+ login => "au@au-win.ne.jp",
+ password => "au",
+ dns => "210.196.3.183",
+ dns => "210.141.112.163",
+ },
+ N("Kenya") . "|Celtel" => {
+ apn => "ke.celtel.com",
+ },
+ N("Kenya") . "|Safaricom" => {
+ apn => "web.safaricom.com",
+ login => "web",
+ password => "web",
+ },
+ N("Kenya") . "|Econet" => {
+ apn => "internet.econet.co.ke",
+ },
+ N("Kuwait") . "|Vodafone" => {
+ apn => "apn01",
+ dns => "10.10.10.30",
+ },
+ N("Kuwait") . "|Wataniya" => {
+ apn => "action.wataniya.com",
+ },
+ N("Kazakhstan") . "|Beeline" => {
+ apn => "internet.beeline.kz",
+ login => "@internet.beeline",
+ dns => "212.19.149.53 ",
+ dns => "194.226.128.1",
+ },
+ N("Laos") . "|ETL" => {
+ apn => "etlnet",
+ dns => "192.168.4.130",
+ },
+ N("Lebanon") . "|Cellis FTML" => {
+ apn => "internet.ftml.com.lb",
+ login => "plugged",
+ password => "plugged",
+ },
+ N("Lebanon") . "|MTC Touch" => {
+ apn => "gprs.mtctouch.com.lb",
+ },
+ N("Lebanon") . "|LibanCell" => {
+ apn => "isurf.libancell.com.lb",
+ },
+ N("Saint Lucia") . "|Cable & Wireless" => {
+ apn => "internet",
+ dns => "-",
+ },
+ N("Sri Lanka") . "|Airtel" => {
+ apn => "www.wap.airtel.lk",
+ },
+ N("Sri Lanka") . "|Dialog GSM (Post-Paid)" => {
+ apn => "www.dialogsl.com",
+ },
+ N("Sri Lanka") . "|Dialog GSM (Pre-Paid)" => {
+ apn => "ppinternet",
+ },
+ N("Sri Lanka") . "|Hutch" => {
+ apn => "htwap",
+ },
+ N("Sri Lanka") . "|Mobitel" => {
+ apn => "isp",
+ },
+ N("Sri Lanka") . "|Tigo" => {
+ apn => "wap",
+ },
+ N("Lithuania") . "|Bite" => {
+ apn => "banga",
+ login => "bite",
+ dns => "213.226.131.131",
+ dns => "193.219.88.36",
+ },
+ N("Lithuania") . "|TELE2 GPRS" => {
+ apn => "internet.tele2.lt",
+ gateway => "130.244.196.90",
+ },
+ N("Lithuania") . "|Omnitel (contract)" => {
+ apn => "gprs.omnitel.net",
+ dns => "194.176.32.129",
+ dns => "195.22.175.1",
+ },
+ N("Lithuania") . "|Omnitel (no contract)" => {
+ apn => "gprs.startas.lt",
+ login => "omni",
+ password => "omni",
+ dns => "194.176.32.129",
+ dns => "195.22.175.1",
+ },
+ N("Luxembourg") . "|LUXGSM" => {
+ apn => "webp.pt.lu",
+ dns => "194.154.192.101",
+ dns => "194.154.192.102",
+ },
+ N("Luxembourg") . "|Tango" => {
+ apn => "internet",
+ login => "tango",
+ password => "tango",
+ },
+ N("Luxembourg") . "|VOXmobile" => {
+ apn => "vox.lu",
+ },
+ N("Latvia") . "|LMT" => {
+ apn => "internet.lmt.lv",
+ dns => "212.93.96.2",
+ dns => "212.93.96.4",
+ },
+ N("Latvia") . "|Tele2" => {
+ apn => "internet.tele2.lv",
+ login => "gprs",
+ password => "internet",
+ },
+ N("Morocco") . "|Maroc Telecom" => {
+ apn => "iam",
+ login => "wac",
+ password => "1987",
+ },
+ N("Morocco") . "|Medi Telecom" => {
+ apn => "wap.meditel.ma",
+ login => "MEDIWAP",
+ password => "MEDIWAP",
+ },
+ N("Moldova") . "|Moldcell" => {
+ apn => "internet",
+ login => "gprs",
+ password => "gprs",
+ },
+ N("Moldova") . "|Eventis" => {
+ apn => "internet.md",
+ },
+ N("Montenegro") . "|Mobtel Srbija" => {
+ apn => "internet",
+ login => "mobtel",
+ password => "gprs",
+ dns => "217.65.192.1",
+ dns => "217.65.192.52",
+ },
+ N("Montenegro") . "|Promonte GSM" => {
+ apn => "gprs.promonte.com",
+ },
+ N("Montenegro") . "|T-Mobile" => {
+ apn => "internet-postpaid",
+ login => "38167",
+ password => "38167",
+ },
+ N("Montenegro") . "|Telekom Srbija (default)" => {
+ apn => "gprsinternet",
+ login => "mts",
+ password => "64",
+ dns => "195.178.38.3",
+ },
+ N("Montenegro") . "|Telekom Srbija (via MMS)" => {
+ apn => "mms",
+ login => "mts",
+ password => "64",
+ dns => "195.178.38.3",
+ },
+ N("Montenegro") . "|Telekom Srbija (via wap)" => {
+ apn => "gprswap",
+ login => "mts",
+ password => "64",
+ dns => "195.178.38.3",
+ },
+ N("Mongolia") . "|MobiCom" => {
+ apn => "internet",
+ },
+ N("Macao") . "|Macau Hutchison Telecom" => {
+ apn => "ctm-mobile",
+ },
+ N("Macao") . "|Macau Hutchison Telecom (MMS)" => {
+ apn => "mms.hutchisonmacau.com",
+ login => "hutchison",
+ password => "1234",
+ },
+ N("Macao") . "|CTM" => {
+ apn => "ctm-mobile",
+ },
+ N("Macao") . "|Macau Hutchison Telecom (Internet)" => {
+ apn => "web.hutchisonmacau.com",
+ login => "hutchison",
+ password => "1234",
+ },
+ N("Malta") . "|Go Mobile (Post-paid)" => {
+ apn => "gosurfing",
+ },
+ N("Malta") . "|Go Mobile (Pre-paid)" => {
+ apn => "rtgsurfing",
+ },
+ N("Malta") . "|Vodafone" => {
+ apn => "Internet",
+ login => "Internet",
+ password => "Internet",
+ },
+ N("Mauritius") . "|Emtel" => {
+ apn => "WEB",
+ },
+ N("Maldives") . "|Dhiraagu" => {
+ apn => "internet.dhimobile",
+ },
+ N("Mexico") . "|TELCEL" => {
+ apn => "internet.itelcel.com",
+ login => "webgprs",
+ password => "webgprs2002",
+ dns => "148.233.151.245",
+ dns => "148.233.151.245",
+ },
+ N("Mexico") . "|Iusacell" => {
+ cdma => 1,
+ },
+ N("Malaysia") . "|DIGI" => {
+ apn => "diginet",
+ dns => "203.92.128.131",
+ dns => "203.92.128.132",
+ },
+ N("Malaysia") . "|Maxis (contract)" => {
+ apn => "internet.gprs.maxis",
+ dns => "202.75.129.101",
+ dns => "10.216.4.21",
+ },
+ N("Malaysia") . "|Maxis (pre-pay)" => {
+ apn => "net",
+ login => "maxis",
+ password => "net",
+ },
+ N("Malaysia") . "|Timecel" => {
+ apn => "timenett.com.my",
+ dns => "203.121.16.85",
+ dns => "203.121.16.120",
+ },
+ N("Malaysia") . "|TM Touch" => {
+ apn => "internet",
+ dns => "202.188.0.133",
+ },
+ N("Malaysia") . "|Celcom" => {
+ apn => "celcom.net.my",
+ },
+ N("Malaysia") . "|Maxis 3G (contract)" => {
+ apn => "unet",
+ login => "maxis",
+ password => "wap",
+ dns => "10.213.17.1",
+ dns => "10.213.17.2",
+ },
+ N("Mozambique") . "|MCel" => {
+ apn => "isp.mcel.mz",
+ login => "guest",
+ password => "guest",
+ dns => "212.96.24.2",
+ dns => "212.96.24.1",
+ },
+ N("Nigeria") . "|Zain" => {
+ apn => "wap",
+ login => "wap",
+ password => "wap",
+ },
+ N("Nigeria") . "|MTN" => {
+ apn => "web.gprs.mtnnigeria.net",
+ login => "web",
+ password => "web",
+ },
+ N("Nigeria") . "|Glo-Ng" => {
+ apn => "glosecure",
+ login => "gprs",
+ password => "gprs",
+ dns => "-",
+ },
+ N("Nicaragua") . "|Alo Pcs" => {
+ apn => "internet.ideasalo.ni",
+ login => "internet",
+ password => "internet",
+ },
+ N("Nicaragua") . "|Movistar" => {
+ apn => "internet.movistar.ni",
+ login => "internet",
+ password => "internet",
+ },
+ N("Netherlands") . "|Hi" => {
+ apn => "portalmmm.nl",
+ },
+ N("Netherlands") . "|KPN Mobile" => {
+ apn => "internet",
+ login => "KPN",
+ password => "gprs",
+ dns => "62.133.126.28",
+ dns => "62.133.126.29",
+ },
+ N("Netherlands") . "|o2" => {
+ apn => "internet",
+ dns => "195.99.65.220",
+ dns => "195.99.66.220",
+ },
+ N("Netherlands") . "|T-Mobile" => {
+ apn => "internet",
+ dns => "193.78.240.12",
+ dns => "193.79.242.39",
+ },
+ N("Netherlands") . "|Telfort" => {
+ apn => "internet",
+ login => "telfortnl",
+ },
+ N("Netherlands") . "|Vodafone" => {
+ apn => "live.vodafone.com",
+ login => "vodafone",
+ password => "vodafone",
+ },
+ N("Netherlands") . "|Vodafone (business)" => {
+ apn => "office.vodafone.nl",
+ login => "vodafone",
+ password => "vodafone",
+ },
+ N("Netherlands") . "|XS4ALL Mobiel Internet" => {
+ apn => "umts.xs4all.nl",
+ },
+ N("Norway") . "|Netcom" => {
+ apn => "internet.netcom.no",
+ login => "netcom",
+ password => "netcom",
+ dns => "212.169.123.67 ",
+ dns => "212.45.188.254",
+ },
+ N("Norway") . "|ice.net (Nordisk Mobiltelefon)" => {
+ cdma => 1,
+ login => "cdma",
+ password => "cdma",
+ },
+ N("Norway") . "|Telenor" => {
+ apn => "internet",
+ dns => "212.17.131.3",
+ dns => "148.122.161.2",
+ },
+ N("Norway") . "|TDC" => {
+ apn => "internet.no",
+ dns => "80.232.41.10",
+ dns => "80.232.41.20",
+ },
+ N("Norway") . "|NetworkNorway" => {
+ apn => "internet",
+ },
+ N("Norway") . "|OneCall" => {
+ apn => "internet",
+ },
+ N("Norway") . "|Lebara" => {
+ apn => "internet",
+ },
+ N("Norway") . "|Altibox" => {
+ apn => "internet",
+ },
+ N("Norway") . "|SheTalks" => {
+ apn => "internet",
+ },
+ N("Norway") . "|Telipol" => {
+ apn => "internet",
+ },
+ N("Nepal") . "|Mero Mobile" => {
+ apn => "mero",
+ },
+ N("New Zealand") . "|Vodafone" => {
+ apn => " live.vodafone.com",
+ dns => "202.20.93.10",
+ dns => "203.97.191.189",
+ },
+ N("New Zealand") . "|Vodafone (restricted)" => {
+ apn => "www.vodafone.net.nz",
+ dns => "202.20.93.10",
+ dns => "203.97.191.189",
+ },
+ N("New Zealand") . "|Vodafone (unrestricted)" => {
+ apn => "internet",
+ dns => "202.20.93.10",
+ dns => "203.97.191.189",
+ },
+ N("Panama") . "|Cable and Wireless" => {
+ apn => "apn01.cwpanama.com.pa",
+ login => "xxx",
+ password => "xxx",
+ },
+ N("Panama") . "|Movistar" => {
+ apn => "internet.movistar.pa",
+ login => "movistarpa",
+ password => "movistarpa",
+ },
+ N("Oman") . "|Nawras" => {
+ apn => "isp.nawras.com.om",
+ },
+ N("Peru") . "|Claro" => {
+ apn => "tim.pe",
+ login => "tim",
+ password => "tulibertad",
+ },
+ N("Philippines") . "|Globe Telecom" => {
+ apn => "internet.globe.com.ph",
+ login => "globe",
+ password => "globe",
+ dns => "203.127.225.10",
+ dns => "203.127.225.11",
+ },
+ N("Philippines") . "|Smart" => {
+ apn => "internet",
+ login => "witsductoor",
+ password => "banonoy",
+ dns => "202.57.96.3",
+ dns => "202.57.96.4",
+ },
+ N("Philippines") . "|Sun Cellular" => {
+ apn => "minternet",
+ },
+ N("Philippines") . "|Globe Telecoms (WAP)" => {
+ apn => "www.globe.com.ph",
+ login => "globe",
+ password => "globe",
+ dns => "203.127.225.10",
+ dns => "203.127.225.11",
+ },
+ N("Pakistan") . "|Djuice" => {
+ apn => "172.18.19.11",
+ login => "telenor",
+ password => "telenor",
+ },
+ N("Pakistan") . "|Mobilink GSM" => {
+ apn => "connect.mobilinkworld.com",
+ },
+ N("Pakistan") . "|Mobilink GSM (jazz)" => {
+ apn => "jazzconnect.mobilinkworld.com",
+ },
+ N("Pakistan") . "|Telenor" => {
+ apn => "internet",
+ login => "telenor",
+ password => "telenor",
+ },
+ N("Pakistan") . "|Ufone" => {
+ apn => "ufone.internet",
+ login => "ufone",
+ password => "ufone",
+ },
+ N("Pakistan") . "|ZONG" => {
+ apn => "zonginternet",
+ },
+ N("Poland") . "|ERA" => {
+ apn => "erainternet",
+ login => "erainternet",
+ password => "erainternet",
+ dns => "213.158.194.1 ",
+ dns => "213.158.193.38",
+ },
+ N("Poland") . "|Idea" => {
+ apn => "www.idea.pl",
+ login => "idea",
+ password => "idea",
+ dns => "194.9.223.79",
+ dns => "217.17.34.10",
+ },
+ N("Poland") . "|Play Online" => {
+ apn => "Internet",
+ },
+ N("Poland") . "|Polkomtel" => {
+ apn => "www.plusgsm.pl",
+ dns => "212.2.96.51 ",
+ dns => "212.2.96.52",
+ },
+ N("Poland") . "|Heyah" => {
+ apn => "heyah.pl",
+ login => "heyah",
+ password => "heyah",
+ dns => "213.158.194.1",
+ dns => "213.158.193.38",
+ },
+ N("Poland") . "|Orange" => {
+ apn => "internet",
+ login => "internet",
+ password => "internet",
+ dns => "194.9.223.79",
+ dns => "194.204.159.1",
+ },
+ N("Poland") . "|iPlus" => {
+ apn => "www.plusgsm.pl",
+ dns => "212.2.96.51",
+ dns => "212.2.96.52",
+ },
+ N("Portugal") . "|Kanguru" => {
+ apn => "myconnection",
+ dns => "62.169.67.172",
+ dns => "62.169.67.171",
+ },
+ N("Portugal") . "|Kanguru (fixo)" => {
+ apn => "kangurufixo",
+ dns => "62.169.67.172",
+ dns => "62.169.67.171",
+ },
+ N("Portugal") . "|Optimus" => {
+ apn => "internet",
+ dns => "194.79.69.129",
+ },
+ N("Portugal") . "|TMN" => {
+ apn => "internet",
+ dns => "194.65.3.20",
+ dns => "194.65.3.21",
+ },
+ N("Portugal") . "|Vodafone" => {
+ apn => "internet.vodafone.pt",
+ dns => "212.18.160.133",
+ dns => "212.18.160.134",
+ },
+ N("Paraguay") . "|CTI" => {
+ apn => "internet.ctimovil.com.py",
+ login => "ctigprs",
+ password => "ctigprs999",
+ },
+ N("Romania") . "|Orange" => {
+ apn => "internet",
+ dns => "172.22.7.21 ",
+ dns => "172.22.7.20",
+ },
+ N("Romania") . "|Vodafone" => {
+ apn => "internet.vodafone.ro",
+ login => "internet.vodafone.ro",
+ password => "vodafone",
+ dns => "193.230.161.3",
+ dns => "193.230.161.4",
+ },
+ N("Romania") . "|Zapp" => {
+ cdma => 1,
+ login => "zapp",
+ password => "zapp",
+ },
+ N("Serbia") . "|Mobtel Srbija" => {
+ apn => "internet",
+ login => "mobtel",
+ password => "gprs",
+ dns => "217.65.192.1",
+ dns => "217.65.192.52",
+ },
+ N("Serbia") . "|Telekom Srbija (default)" => {
+ apn => "gprsinternet",
+ login => "mts",
+ password => "64",
+ dns => "195.178.38.3",
+ },
+ N("Serbia") . "|Telekom Srbija (via MMS)" => {
+ apn => "mms",
+ login => "mts",
+ password => "64",
+ dns => "195.178.38.3",
+ },
+ N("Serbia") . "|Telekom Srbija (via wap)" => {
+ apn => "gprswap",
+ login => "mts",
+ password => "64",
+ dns => "195.178.38.3",
+ },
+ N("Russian Federation") . "|BaikalWestCom" => {
+ apn => "inet.bwc.ru",
+ login => "bwc",
+ password => "bwc",
+ dns => "81.18.113.2",
+ dns => "81.18.112.50",
+ },
+ N("Russian Federation") . "|Beeline" => {
+ apn => "internet.beeline.ru",
+ login => "beeline",
+ password => "beeline",
+ dns => "217.118.66.243",
+ dns => "217.118.66.244",
+ },
+ N("Russian Federation") . "|Megafon (nw)" => {
+ apn => "internet.nw",
+ dns => "10.140.142.42 ",
+ dns => "10.140.142.45",
+ },
+ N("Russian Federation") . "|МТС" => {
+ apn => "internet.mts.ru",
+ login => "mts",
+ password => "mts",
+ dns => "213.87.0.1",
+ dns => "213.87.1.1",
+ },
+ N("Russian Federation") . "|PrimTelephone" => {
+ apn => "internet.primtel.ru",
+ },
+ N("Russian Federation") . "|Megafon (ugsm)" => {
+ apn => "internet.ugsm",
+ dns => "83.149.32.2 ",
+ dns => "83.149.33.2",
+ },
+ N("Russian Federation") . "|Megafon (usi)" => {
+ apn => "internet.usi.ru",
+ dns => "212.120.160.130 ",
+ dns => "212.120.160.130",
+ },
+ N("Russian Federation") . "|Megafon (dv)" => {
+ apn => "internet.dv",
+ dns => "83.149.52.77",
+ dns => "194.186.112.18",
+ },
+ N("Russian Federation") . "|Megafon (kvk)" => {
+ apn => "internet.kvk",
+ dns => "83.149.24.244 ",
+ dns => "62.183.50.230",
+ },
+ N("Russian Federation") . "|Megafon (ltmsk)" => {
+ apn => "internet.ltmsk",
+ dns => "10.22.10.20 ",
+ dns => "10.22.10.21",
+ },
+ N("Russian Federation") . "|Megafon (sib)" => {
+ apn => "internet.sib",
+ dns => "83.149.51.65 ",
+ dns => "83.149.50.65",
+ },
+ N("Russian Federation") . "|Megafon (volga)" => {
+ apn => "internet.volga",
+ dns => "83.149.16.7 ",
+ dns => "195.128.128.1",
+ },
+ N("Russian Federation") . "|Megafon (mc)" => {
+ apn => "internet.mc",
+ dns => "81.18.129.252 ",
+ dns => "217.150.34.1",
+ },
+ N("Russian Federation") . "|NCC" => {
+ apn => "internet",
+ login => "ncc",
+ dns => "10.0.3.5 ",
+ dns => "10.0.3.2",
+ },
+ N("Russian Federation") . "|NTC" => {
+ apn => "internet.ntc",
+ dns => "80.243.64.67 ",
+ dns => "80.243.68.34",
+ },
+ N("Russian Federation") . "|Megafon (Moscow)" => {
+ apn => "internet",
+ login => "gdata",
+ password => "gdata",
+ },
+ N("Russian Federation") . "|Enisey TeleCom" => {
+ apn => "internet.etk.ru",
+ login => "etk",
+ dns => "10.10.30.3",
+ dns => "10.10.30.4",
+ },
+ N("Russian Federation") . "|Motiv" => {
+ apn => "inet.ycc.ru",
+ login => "motiv",
+ dns => "217.148.52.34",
+ dns => "217.148.52.3",
+ },
+ N("Russian Federation") . "|Tatincom" => {
+ apn => "internet.tatincom.ru",
+ login => "tatincom",
+ password => "tatincom",
+ dns => "89.207.96.2",
+ dns => "89.207.97.18",
+ },
+ N("Russian Federation") . "|Tele2" => {
+ apn => "wap.tele2.ru",
+ login => "gprs",
+ dns => "130.244.127.161",
+ dns => "130.244.127.169",
+ },
+ N("Russian Federation") . "|Skylink (Moscow)" => {
+ cdma => 1,
+ login => "mobile@skylink.msk.ru",
+ password => "internet",
+ },
+ N("Saudi Arabia") . "|Mobily" => {
+ apn => "web2",
+ },
+ N("Saudi Arabia") . "|STC" => {
+ apn => "jawalnet.com.sa",
+ dns => "212.118.133.101",
+ dns => "212.118.133.102",
+ },
+ N("Sweden") . "|3 (Mobiltelefon)" => {
+ apn => "data.tre.se",
+ },
+ N("Sweden") . "|3 (Bredband)" => {
+ apn => "bredband.tre.se",
+ },
+ N("Sweden") . "|3 (Bredband Kontantkort)" => {
+ apn => "net.tre.se",
+ },
+ N("Sweden") . "|Glocalnet" => {
+ apn => "internet.glocalnet.se",
+ },
+ N("Sweden") . "|Halebop" => {
+ apn => "halebop.telia.se",
+ },
+ N("Sweden") . "|ice.net (Nordisk Mobiltelefon)" => {
+ cdma => 1,
+ login => "cdma",
+ password => "cdma",
+ },
+ N("Sweden") . "|Tele2/Comviq" => {
+ apn => "internet.tele2.se",
+ },
+ N("Sweden") . "|Telenor" => {
+ apn => "internet.telenor.se",
+ },
+ N("Sweden") . "|Telia" => {
+ apn => "online.telia.se",
+ },
+ N("Singapore") . "|M1" => {
+ apn => "sunsurf",
+ login => "65",
+ password => "user123",
+ dns => "202.79.64.21",
+ dns => "202.79.64.26",
+ },
+ N("Singapore") . "|SingTel" => {
+ apn => "internet",
+ dns => "165.21.100.88",
+ dns => "165.21.83.88",
+ },
+ N("Singapore") . "|Starhub" => {
+ apn => "shwap",
+ login => "star",
+ password => "hub",
+ dns => "203.116.1.78",
+ },
+ N("Slovenia") . "|Mobitel (postpaid)" => {
+ apn => "internet",
+ login => "mobitel",
+ password => "internet",
+ dns => "213.229.248.161 ",
+ dns => "193.189.160.11",
+ },
+ N("Slovenia") . "|Mobitel (prepaid)" => {
+ apn => "internetpro",
+ login => "mobitel",
+ password => "internet",
+ dns => "213.229.248.161 ",
+ dns => "193.189.160.11",
+ },
+ N("Slovenia") . "|Simobil" => {
+ apn => "none",
+ dns => "121.30.86.130",
+ dns => "193.189.160.11",
+ },
+ N("Slovakia") . "|T-Mobile (EuroTel)" => {
+ apn => "internet",
+ dns => "194.154.230.66 ",
+ dns => "194.154.230.74",
+ },
+ N("Slovakia") . "|Globtel" => {
+ apn => "internet",
+ dns => "213.151.200.3",
+ dns => "195.12.140.130",
+ },
+ N("Slovakia") . "|Orange" => {
+ apn => "internet",
+ login => "jusernejm",
+ password => "pasvord",
+ dns => "213.151.200.30 ",
+ dns => "213.151.208.161",
+ },
+ N("Slovakia") . "|Eurotel" => {
+ apn => "internet",
+ dns => "194.154.230.64",
+ dns => "194.154.230.74",
+ },
+ N("Senegal") . "|Tigo" => {
+ apn => "internet.tigo.hn",
+ dns => "200.85.0.104",
+ dns => "200.85.0.107",
+ },
+ N("El Salvador") . "|movistar" => {
+ apn => "movistar.sv",
+ login => "movistarsv",
+ password => "movistarsv",
+ },
+ N("Thailand") . "|AIS" => {
+ apn => "internet",
+ dns => "202.183.255.20",
+ dns => "202.183.255.21",
+ },
+ N("Thailand") . "|DTAC" => {
+ apn => "www.dtac.co.th",
+ dns => "202.44.202.2",
+ dns => "203.44.144.33",
+ },
+ N("Thailand") . "|True" => {
+ apn => "internet",
+ login => "true",
+ password => "true",
+ },
+ N("Turkey") . "|Aria" => {
+ apn => "internet",
+ dns => "212.156.4.4",
+ dns => "212.156.4.20",
+ },
+ N("Turkey") . "|Aycell" => {
+ apn => "aycell",
+ dns => "212.156.4.1",
+ dns => "212.156.4.4",
+ },
+ N("Turkey") . "|Turkcell" => {
+ apn => "internet",
+ login => "gprs",
+ password => "gprs",
+ dns => "86.108.136.27",
+ dns => "86.108.136.26",
+ },
+ N("Turkey") . "|Telsim (Post-paid)" => {
+ apn => "telsim",
+ login => "telsim",
+ password => "telsim",
+ dns => "212.65.128.20",
+ dns => "212.156.4.7",
+ },
+ N("Turkey") . "|Telsim (pre-paid)" => {
+ apn => "prepaidgprs",
+ dns => "212.65.128.20",
+ dns => "212.156.4.7",
+ },
+ N("Trinidad and Tobago") . "|Digicel" => {
+ apn => "wap.digiceltt.com",
+ login => "wap",
+ password => "wap",
+ },
+ N("Trinidad and Tobago") . "|TSTT" => {
+ apn => "internet",
+ login => "wap",
+ password => "wap",
+ },
+ N("Taiwan") . "|Chunghwa Telecom (emome)" => {
+ apn => "internet",
+ },
+ N("Taiwan") . "|Far EasTone / KGT" => {
+ apn => "internet",
+ },
+ N("Taiwan") . "|TW Mobile / TransAsia" => {
+ apn => "internet",
+ },
+ N("Taiwan") . "|Vibo Telecom / Aurora" => {
+ apn => "vibo",
+ },
+ N("Taiwan") . "|Asia Pacific Telecom (APBW)" => {
+ cdma => 1,
+ },
+ N("Ukraine") . "|Jeans" => {
+ apn => "www.jeans.ua",
+ dns => "80.255.64.23",
+ dns => "80.255.64.24",
+ },
+ N("Ukraine") . "|Djuice" => {
+ apn => "www.djuice.com.ua",
+ dns => "212.58.160.33",
+ dns => "212.58.160.34",
+ },
+ N("Ukraine") . "|Mobi-GSM" => {
+ apn => "internet.urs",
+ dns => "213.186.192.254",
+ dns => "193.239.128.5",
+ },
+ N("Ukraine") . "|Ace&Base" => {
+ apn => "www.ab.kyivstar.net",
+ login => "igprs",
+ password => "internet",
+ },
+ N("Ukraine") . "|Life (standard)" => {
+ apn => "internet",
+ dns => "212.58.160.33",
+ dns => "212.58.160.34",
+ },
+ N("Ukraine") . "|Beeline" => {
+ apn => "internet.beeline.ua",
+ },
+ N("Ukraine") . "|Life (faster)" => {
+ apn => "speed",
+ dns => "212.58.160.33",
+ dns => "212.58.160.34",
+ },
+ N("Ukraine") . "|Wellcome" => {
+ apn => "internet.urs",
+ dns => "213.186.192.254",
+ dns => "193.239.128.5",
+ },
+ N("Ukraine") . "|Jeans (Hyper)" => {
+ apn => "hyper.net",
+ dns => "212.58.160.33",
+ dns => "212.58.160.34",
+ },
+ N("Ukraine") . "|UMC (internet)" => {
+ apn => "internet",
+ login => "internet",
+ dns => "212.58.160.33",
+ dns => "212.58.160.34",
+ },
+ N("Ukraine") . "|UMC (umc.ua)" => {
+ apn => "www.umc.ua",
+ dns => "80.255.64.23",
+ dns => "80.255.64.24",
+ },
+ N("Ukraine") . "|Utel" => {
+ apn => "3g.utel.ua",
+ },
+ N("Uganda") . "|MTN" => {
+ apn => "yellopix.mtn.co.ug",
+ dns => "212.88.97.20",
+ dns => "212.88.97.67",
+ },
+ N("United States") . "|AT&T" => {
+ apn => "WAP.CINGULAR",
+ login => "WAP@CINGULARGPRS.COM",
+ password => "CINGULAR1",
+ },
+ N("United States") . "|AT&T (Tethering)" => {
+ apn => "ISP.CINGULAR",
+ login => "ISP@CINGULARGPRS.COM",
+ password => "CINGULAR1",
+ },
+ N("United States") . "|AT&T (Tethering with data acceleration)" => {
+ apn => "ISP.CINGULAR",
+ login => "ISPDA@CINGULARGPRS.COM",
+ password => "CINGULAR1",
+ },
+ N("United States") . "|T-Mobile (Web)" => {
+ apn => "wap.voicestream.com",
+ },
+ N("United States") . "|T-Mobile (Internet)" => {
+ apn => "internet2.voicestream.com",
+ },
+ N("United States") . "|T-Mobile (Internet with VPN)" => {
+ apn => "internet3.voicestream.com",
+ },
+ N("United States") . "|Sprint" => {
+ cdma => 1,
+ },
+ N("United States") . "|Boost Mobile (Prepaid)" => {
+ cdma => 1,
+ },
+ N("United States") . "|Verizon" => {
+ cdma => 1,
+ },
+ N("United States") . "|US Cellular" => {
+ cdma => 1,
+ },
+ N("United States") . "|Alltel" => {
+ cdma => 1,
+ },
+ N("United States") . "|Leap Wireless" => {
+ cdma => 1,
+ },
+ N("United States") . "|Cricket Communications" => {
+ cdma => 1,
+ },
+ N("United States") . "|Jump Mobile (Prepaid)" => {
+ cdma => 1,
+ },
+ N("United States") . "|MetroPCS" => {
+ cdma => 1,
+ },
+ N("Uruguay") . "|Ancel" => {
+ apn => "gprs.ancel",
+ dns => "200.40.30.245 ",
+ dns => "200.40.220.245",
+ },
+ N("Uruguay") . "|CTI" => {
+ apn => "internet.ctimovil.com.uy",
+ login => "ctiweb",
+ password => "ctiweb999",
+ },
+ N("Uruguay") . "|Movistar" => {
+ apn => "webapn.movistar.com.uy",
+ login => "movistar",
+ password => "movistar",
+ },
+ N("Uzbekistan") . "|Uzdunrobita" => {
+ apn => "net.urd.uz",
+ login => "user",
+ password => "pass",
+ },
+ N("Saint Vincent and the Grenadines") . "|Digicel" => {
+ apn => "wap.digiceloecs.com",
+ login => "wapoecs",
+ password => "wap03oecs",
+ },
+ N("Venezuela") . "|Digitel TIM" => {
+ apn => "gprsweb.digitel.ve",
+ dns => "57.67.127.195",
+ },
+ N("South Africa") . "|Cell-c" => {
+ apn => "internet",
+ login => "Cellcis",
+ password => "Crap",
+ dns => "196.7.0.138",
+ dns => "196.7.142.132",
+ },
+ N("South Africa") . "|MTN" => {
+ apn => "internet",
+ dns => "196.11.240.241",
+ dns => "209.212.97.1",
+ },
+ N("South Africa") . "|Vodacom" => {
+ apn => "internet",
+ dns => "196.207.40.165",
+ dns => "196.43.46.190",
+ },
+ N("South Africa") . "|Virgin Mobile" => {
+ apn => "vdata",
+ dns => "196.7.0.138",
+ dns => "196.7.142.132",
+ },
+ N("South Africa") . "|Vodacom (unrestricted APN)" => {
+ apn => "unrestricted",
+ dns => "196.207.32.69",
+ dns => "196.43.45.190",
+ },
+);
+
+1;
diff --git a/lib/network/connection/providers/xdsl.pm b/lib/network/connection/providers/xdsl.pm
new file mode 100644
index 0000000..52b1b58
--- /dev/null
+++ b/lib/network/connection/providers/xdsl.pm
@@ -0,0 +1,1352 @@
+# -*- coding: utf-8 -*-
+package network::connection::providers::xdsl; # $Id: xdsl.pm 59309 2006-09-01 12:08:15Z tv $
+
+# This should probably be splitted out into ldetect-lst as some provider db
+
+use common;
+use utf8;
+
+# Originally from :
+# http://www.eagle-usb.org/article.php3?id_article=23
+# http://www.sagem.com/web-modems/download/support-fast1000-fr.htm
+# http://perso.wanadoo.fr/michel-m/protocolesfai.htm
+# Then other ISP found in :
+# http://www.adslayuda.com/Comtrend500+file-16.html
+
+# the output is provided in html at http://faq.eagle-usb.org/wakka.php?wiki=ListConfigADSL
+# this file should be put in /usr/share/eagle-usb/ for eagle-usb driver
+# or in /usr/lib/libDrakX/network/ as part of the drakxtools
+
+our %data = (
+ ## format chosen is the following :
+ # country|provider => { VPI, VCI_hexa, ... } all parameters
+ # country is automagically translated into LANG with N function
+ # provider is kept "as-is", not translated
+ # provider_id is used by eagleconfig to identify an ISP (I use ISO_3166-1)
+ # see http://en.wikipedia.org/wiki/ISO_3166-1
+ # url_tech : technical URL providing info about ISP
+ # vpi : virtual path identifier
+ # vci : virtual channel identifier (in hexa below !!)
+ # Encapsulation:
+ # 1=PPPoE LLC, 2=PPPoE VCmux (never used ?)
+ # 3=RFC1483/2684 Routed IP LLC,
+ # 4=RFC1483/2684 Routed IP (IPoA VCmux)
+ # 5 RFC2364 PPPoA LLC,
+ # 6 RFC2364 PPPoA VCmux
+ # see http://faq.eagle-usb.org/wakka.php?wiki=AdslDescription
+ # dns are provided for when !usepeerdns in peers config file
+ # dnsServers : array ref with any valid DNS (order matters)
+ # DOMAINNAME2 : used for search key in /etc/resolv.conf
+ # method : PPPoA, pppoe, static or dhcp
+ # login_format : e.g. fti/login for France Telecom
+ # encryption : for pppd connection, when encryption is supported
+ # modem : model of modem provided by ISP or tested with ISP
+ # please forward updates to http://forum.eagle-usb.org
+ # try to order alphabetically by country (in English) / ISP (local language)
+
+ N("Algeria") . "|Wanadoo" =>
+ {
+ provider_id => 'DZ01',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 1,
+ method => 'pppoe',
+ dnsServers => [ qw(82.101.136.29 82.101.136.206) ],
+ },
+
+ N("Algeria") . "|Algerie Telecom (FAWRI)" =>
+ {
+ provider_id => 'DZ02',
+ vpi => 0,
+ vci => 26,
+ Encapsulation => 1,
+ method => 'pppoe',
+ dnsServers => [ qw(61.88.88.88 205.252.144.228) ],
+ },
+
+ N("Argentina") . "|Speedy" =>
+ {
+ provider_id => 'AR01',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 1,
+ method => 'pppoe',
+ dnsServers => [ qw(200.51.254.238 200.51.209.22) ],
+ },
+
+ N("Argentina") . "|Arnet" =>
+ {
+ provider_id => 'AR02',
+ vpi => 8,
+ vci => 21,
+ Encapsulation => 1,
+ method => 'pppoe',
+ dnsServers => [ qw(200.45.191.35 200.45.191.40) ],
+ },
+
+ N("Austria") . "|" . N("Any") =>
+ {
+ provider_id => 'AT00',
+ vpi => 8,
+ vci => 30,
+ Encapsulation => 6,
+ method => 'pppoa',
+ },
+
+ N("Austria") . "|AON" =>
+ {
+ provider_id => 'AT01',
+ vpi => 1,
+ vci => 20,
+ Encapsulation => 6,
+ method => 'pppoa',
+ },
+
+ N("Austria") . "|Telstra" =>
+ {
+ provider_id => 'AT02',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 1,
+ method => 'pppoe',
+ },
+
+ N("Australia") . "|Arachnet" =>
+ {
+ provider_id => 'AU01',
+ url_tech => "http://www.ains.com.au/consumer/support/technical.htm",
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ method => 'pppoa',
+ },
+
+ N("Australia") . "|Speedstream On net" =>
+ {
+ provider_id => 'AU02',
+ url_tech => "http://www.ains.com.au/consumer/support/technical.htm",
+ vpi => 8,
+ vci => 22,
+ Encapsulation => 6,
+ method => 'pppoa',
+ },
+
+ N("Australia") . "|Speedstream Off net" =>
+ {
+ provider_id => 'AU03',
+ url_tech => "http://www.ains.com.au/consumer/support/technical.htm",
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 1,
+ method => 'pppoe',
+ },
+
+ N("Belgium") . "|ADSL Office" =>
+ {
+ provider_id => 'BE04',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("Belgium") . "|Tiscali BE" =>
+ {
+ provider_id => 'BE01',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ method => 'pppoa',
+ dnsServers => [ qw(212.35.2.1 212.35.2.2 212.233.1.34 212.233.2.34) ],
+ DOMAINNAME2 => 'tiscali.be',
+ },
+
+ N("Belgium") . "|Belgacom" =>
+ {
+ provider_id => 'BE03',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ method => 'pppoa',
+ },
+
+ N("Belgium") . "|Turboline" =>
+ {
+ provider_id => 'BE02',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 5,
+ method => 'pppoa',
+ },
+
+ N("Belgium") . "|Scarlet ADSL" =>
+ {
+ provider_id => 'BE05',
+ vpi => 8,
+ vci => 20,
+ Encapsulation => 6,
+ method => 'pppoa',
+ },
+
+ N("Brazil") . "|Speedy/Telefonica" =>
+ {
+ provider_id => 'BR01',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 1,
+ method => 'pppoe',
+ dnsServers => [ qw(200.204.0.10 200.204.0.138) ],
+ },
+
+ N("Brazil") . "|Velox/Telemar" =>
+ {
+ provider_id => 'BR02',
+ vpi => 0,
+ vci => 21,
+ Encapsulation => 1,
+ method => 'pppoe',
+ },
+
+ N("Brazil") . "|Turbo/Brasil Telecom" =>
+ {
+ provider_id => 'BR03',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 1,
+ method => 'pppoe',
+ },
+
+ N("Brazil") . "|Rio Grande do Sul (RS)" =>
+ {
+ provider_id => 'BR04',
+ vpi => 1,
+ vci => 20,
+ Encapsulation => 1,
+ method => 'pppoe',
+ },
+
+ N("Bulgaria") . "|BTK ISDN" =>
+ {
+ provider_id => 'BG02',
+ vpi => 1,
+ vci => 20,
+ Encapsulation => 1,
+ method => 'pppoe',
+ },
+
+ N("Bulgaria") . "|BTK POTS" =>
+ {
+ provider_id => 'BG01',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 1,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Netcom|Beijing" =>
+ {
+ provider_id => 'CN01',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Netcom|Changchun" =>
+ {
+ provider_id => 'CN02',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Netcom|Harbin" =>
+ {
+ provider_id => 'CN03',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Netcom|Jilin" =>
+ {
+ provider_id => 'CN04',
+ vpi => 0,
+ vci => 27,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Netcom|Lanzhou" =>
+ {
+ provider_id => 'CN05',
+ vpi => 0,
+ vci => 20,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Netcom|Tianjin" =>
+ {
+ provider_id => 'CN06',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Netcom|Xi'an" =>
+ {
+ provider_id => 'CN07',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Telecom|Chongqing" =>
+ {
+ provider_id => 'CN08',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Telecom|Fujian" =>
+ {
+ provider_id => 'CN09',
+ vpi => 0,
+ vci => 0xc8,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Telecom|Guangxi" =>
+ {
+ provider_id => 'CN10',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Telecom|Guangzhou" =>
+ {
+ provider_id => 'CN11',
+ vpi => 8,
+ vci => 20,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Telecom|Hangzhou" =>
+ {
+ provider_id => 'CN12',
+ vpi => 0,
+ vci => 20,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Netcom|Hunan" =>
+ {
+ provider_id => 'CN13',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Telecom|Nanjing" =>
+ {
+ provider_id => 'CN14',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Telecom|Shanghai" =>
+ {
+ provider_id => 'CN15',
+ vpi => 8,
+ vci => 51,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Telecom|Shenzhen" =>
+ {
+ provider_id => 'CN16',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Telecom|Urumqi" =>
+ {
+ provider_id => 'CN17',
+ vpi => 0,
+ vci => 20,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Telecom|Wuhan" =>
+ {
+ provider_id => 'CN18',
+ vpi => 0,
+ vci => 20,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Telecom|Yunnan" =>
+ {
+ provider_id => 'CN19',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("China") . "|China Telecom|Zhuhai" =>
+ {
+ provider_id => 'CN20',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("Czech Republic") . "|Cesky Telecom PPPoA" =>
+ {
+ provider_id => 'CZ01',
+ url_tech => 'http://www.telecom.cz/domacnosti/internet/pristupove_sluzby/broadband/vse_o_kz_a_moznostech_instalace.php',
+ vpi => 8,
+ vci => 30,
+ Encapsulation => 6,
+ method => 'pppoa',
+ },
+
+ N("Czech Republic") . "|Cesky Telecom PPPoE" =>
+ {
+ provider_id => 'CZ02',
+ url_tech => 'http://www.telecom.cz/zakaznicka_podpora/dokumenty_ke_stazeni/internet_expres.php',
+ vpi => 8,
+ vci => 30,
+ Encapsulation => 1,
+ method => 'pppoe',
+ },
+
+ N("Denmark") . "|" . N("Any") =>
+ {
+ provider_id => 'DK01',
+ vpi => 0,
+ vci => 65,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("Denmark") . "|Cybercity" =>
+ {
+ provider_id => 'DK02',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 6,
+ method => 'pppoa',
+ },
+
+ N("Denmark") . "|Tiscali" =>
+ {
+ provider_id => 'DK03',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 6,
+ method => 'pppoa',
+ },
+
+ N("Egypt") . "|Raya Telecom" =>
+ {
+ provider_id => 'EG01',
+ vpi => 8,
+ vci => 50,
+ method => 'pppoa',
+ Encapsulation => 6,
+ dnsServers => [ qw(62.240.110.197 62.240.110.198) ],
+ },
+
+ N("Finland") . "|Sonera" =>
+ {
+ provider_id => 'FI01',
+ vpi => 0,
+ vci => 64,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("France") . "|Free non dégroupé 512/128 & 1024/128" =>
+ {
+ provider_id => 'FR01',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ CMVep => 'FR',
+ dnsServers => [ qw(213.228.0.23 212.27.32.176) ],
+ method => 'pppoa',
+ DOMAINNAME2 => 'free.fr',
+ },
+
+ N("France") . "|Free non dégroupé ADSL Max" =>
+ {
+ provider_id => 'FR11',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ CMVep => 'FR04',
+ dnsServers => [ qw(213.228.0.23 212.27.32.176) ],
+ method => 'pppoa',
+ DOMAINNAME2 => 'free.fr',
+ },
+
+ N("France") . "|Free dégroupé 1024/256 (mini)" =>
+ {
+ provider_id => 'FR04',
+ vpi => 8,
+ vci => 24,
+ Encapsulation => 4,
+ CMVep => 'FR04',
+ dnsServers => [ qw(213.228.0.23 212.27.32.176 213.228.0.68 212.27.32.176 212.27.32.177 212.27.39.2 212.27.39.1) ],
+ method => 'dhcp',
+ DOMAINNAME2 => 'free.fr',
+ },
+
+ N("France") . "|n9uf tel9com 512 & dégroupé 1024" =>
+ {
+ provider_id => 'FR05',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ CMVep => 'FR',
+ dnsServers => [ qw(212.30.93.108 212.203.124.146 62.62.156.12 62.62.156.13) ],
+ method => 'pppoa',
+ },
+
+ N("France") . "|Cegetel non dégroupé 512 IP/ADSL et dégroupé" =>
+ {
+ provider_id => 'FR08',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ CMVep => 'FR',
+ dnsServers => [ qw(212.94.174.85 212.94.174.86) ],
+ method => 'pppoa',
+ login_format => 'login@cegetel.net',
+ },
+
+ N("France") . "|Cegetel ADSL Max 8 Mb" =>
+ {
+ provider_id => 'FR10',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ CMVep => 'FR10',
+ dnsServers => [ qw(212.94.174.85 212.94.174.86) ],
+ method => 'pppoa',
+ login_format => 'login@cegetel.net',
+ },
+
+ N("France") . "|Club-Internet" =>
+ {
+ provider_id => 'FR06',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ CMVep => 'FR',
+ dnsServers => [ qw(194.117.200.10 194.117.200.15) ],
+ method => 'pppoa',
+ DOMAINNAME2 => 'club-internet.fr',
+ },
+
+ N("France") . "|Orange" =>
+ {
+ provider_id => 'FR09',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ CMVep => 'FR',
+ dnsServers => [ qw(80.10.246.2 80.10.246.129) ],
+ method => 'pppoa',
+ login_format => 'fti/login',
+ DOMAINNAME2 => 'orange.fr',
+ },
+
+ N("France") . "|Télé2" =>
+ {
+ provider_id => 'FR02',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ CMVep => 'FR',
+ dnsServers => [ qw(212.151.136.242 130.244.127.162 212.151.136.246) ],
+ method => 'pppoa',
+ },
+
+ N("France") . "|Tiscali.fr 128k" =>
+ {
+ provider_id => 'FR03',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 5,
+ CMVep => 'FR',
+ dnsServers => [ qw(213.36.80.1 213.36.80.2) ],
+ method => 'pppoa',
+ },
+
+ N("France") . "|Tiscali.fr 512k" =>
+ {
+ provider_id => 'FR07',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ CMVep => 'FR',
+ dnsServers => [ qw(213.36.80.1 213.36.80.2) ],
+ method => 'pppoa',
+ },
+
+ N("Germany") . "|Deutsche Telekom (DT)" =>
+ {
+ provider_id => 'DE01',
+ vpi => 1,
+ vci => 20,
+ Encapsulation => 1,
+ method => 'pppoe',
+ },
+
+ N("Germany") . "|1&1" =>
+ {
+ provider_id => 'DE02',
+ vpi => 1,
+ vci => 20,
+ Encapsulation => 1,
+ dnsServers => [ qw(195.20.224.234 194.25.2.129) ],
+ method => 'pppoe',
+ },
+
+ N("Germany") . "|Alice DSL" =>
+ {
+ provider_id => 'DE03',
+ vpi => 1,
+ vci => 20,
+ Encapsulation => 1,
+ dnsServers => [ qw(213.191.73.65 213.191.74.20) ],
+ method => 'pppoe',
+ },
+
+ N("Greece") . "|" . N("Any") =>
+ {
+ provider_id => 'GR01',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ method => 'pppoa',
+ },
+
+ N("Hungary") . "|Matav" =>
+ {
+ provider_id => 'HU01',
+ vpi => 1,
+ vci => 20,
+ Encapsulation => 1,
+ method => 'pppoe',
+ },
+
+ N("Ireland") . "|" . N("Any") =>
+ {
+ provider_id => 'IE01',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 1,
+ method => 'pppoe',
+ },
+
+ N("Israel") . "|Barak 013" =>
+ {
+ provider_id => 'IL03',
+ vpi => 8,
+ vci => 48,
+ Encapsulation => 6,
+ dnsServers => [ qw(212.150.49.10 206.49.94.234 212.150.48.169) ],
+ method => 'pppoa'
+ },
+
+ N("Israel") . "|Bezeq 014" =>
+ {
+ provider_id => 'IL04',
+ vpi => 8,
+ vci => 48,
+ Encapsulation => 6,
+ dnsServers => [ qw(192.115.106.10 192.115.106.11 192.115.106.35) ],
+ method => 'pppoa'
+ },
+
+ N("Israel") . "|Bezeq" =>
+ {
+ provider_id => 'IL01',
+ vpi => 8,
+ vci => 30,
+ Encapsulation => 6,
+ dnsServers => [ qw(192.115.106.10 192.115.106.11 192.115.106.35) ],
+ method => 'pppoa',
+ },
+
+ N("Israel") . "|BGU" =>
+ {
+ provider_id => 'IL06',
+ vpi => 8,
+ vci => 48,
+ Encapsulation => 6,
+ dnsServers => [ qw(132.72.140.46 132.72.140.45) ],
+ method => 'pppoa'
+ },
+
+ N("Israel") . "|HaifaU" =>
+ {
+ provider_id => 'IL07',
+ vpi => 8,
+ vci => 48,
+ Encapsulation => 6,
+ dnsServers => [ qw(132.74.1.3 132.74.1.5) ],
+ method => 'pppoa'
+ },
+
+ N("Israel") . "|HUJI" =>
+ {
+ provider_id => 'IL08',
+ vpi => 8,
+ vci => 48,
+ Encapsulation => 6,
+ dnsServers => [ qw(128.139.6.1 128.139.4.3) ],
+ method => 'pppoa'
+ },
+
+ N("Israel") . "|Kavey Zahave 012" =>
+ {
+ provider_id => 'IL02',
+ vpi => 8,
+ vci => 48,
+ Encapsulation => 6,
+ dnsServers => [ qw(212.117.129.3 212.117.128.6) ],
+ method => 'pppoa'
+ },
+
+ N("Israel") . "|Netvision 017" =>
+ {
+ provider_id => 'IL01',
+ vpi => 8,
+ vci => 48,
+ Encapsulation => 6,
+ dnsServers => [ qw(212.143.212.143 194.90.1.5) ],
+ method => 'pppoa'
+ },
+
+ N("Israel") . "|Smile 015" =>
+ {
+ provider_id => 'IL05',
+ vpi => 8,
+ vci => 48,
+ Encapsulation => 6,
+ dnsServers => [ qw(192.116.202.222 213.8.172.83) ],
+ method => 'pppoa'
+ },
+
+ N("Israel") . "|TAU" =>
+ {
+ provider_id => 'IL09',
+ vpi => 8,
+ vci => 48,
+ Encapsulation => 6,
+ dnsServers => [ qw(132.66.32.10 132.66.16.2) ],
+ method => 'pppoa'
+ },
+
+ N("Israel") . "|Technion" =>
+ {
+ provider_id => 'IL10',
+ vpi => 8,
+ vci => 48,
+ Encapsulation => 6,
+ dnsServers => [ qw(132.68.1.2 132.68.1.9) ],
+ method => 'pppoa'
+ },
+
+ N("India") . "|" . N("Any") =>
+ {
+ provider_id => 'IN01',
+ vpi => 0,
+ vci => 20,
+ Encapsulation => 6,
+ method => 'pppoa',
+ },
+
+ N("Iceland") . "|Islandssimi" =>
+ {
+ provider_id => 'IS01',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 6,
+ method => 'pppoa',
+ },
+
+ N("Iceland") . "|Landssimi" =>
+ {
+ provider_id => 'IS02',
+ vpi => 8,
+ vci => 30,
+ Encapsulation => 6,
+ method => 'pppoa',
+ },
+
+ N("Italy") . "|Telecom Italia" =>
+ {
+ provider_id => 'IT01',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ CMVep => 'IT',
+ dnsServers => [ qw(195.20.224.234 194.25.2.129) ],
+ method => 'pppoa',
+ },
+
+ N("Italy") . "|Telecom Italia/Office Users (ADSL Smart X)" =>
+ {
+ provider_id => 'IT02',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 3,
+ CMVep => 'IT',
+ method => 'static',
+ },
+
+ N("Italy") . "|Tiscali.it, Alice" =>
+ {
+ provider_id => 'IT03',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ CMVep => 'IT',
+ dnsServers => [ qw(195.20.224.234 194.25.2.129) ],
+ method => 'pppoa',
+ },
+
+ N("Italy") . "|Libero.it" =>
+ {
+ provider_id => 'IT04',
+ url_tech => 'http://internet.libero.it/assistenza/adsl/installazione_ass.phtml',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ CMVep => 'IT',
+ dnsServers => [ qw(193.70.192.25 193.70.152.25) ],
+ method => 'pppoa',
+ },
+
+ N("Sri Lanka") . "|Srilanka Telecom" =>
+ {
+ provider_id => 'LK01',
+ url_tech => 'http://www.sltnet.lk',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ dnsServers => [ qw(203.115.0.1 203.115.0.18) ],
+ method => 'pppoa',
+ encryption => 1,
+ },
+
+ N("Lithuania") . "|Lietuvos Telekomas" =>
+ {
+ provider_id => 'LT01',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 1,
+ method => 'pppoe',
+ },
+
+ N("Mauritius") . "|wanadoo.mu" =>
+ {
+ provider_id => 'MU01',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ dnsServers => [ qw(202.123.2.6 202.123.2.11) ],
+ method => 'pppoa',
+ },
+
+ N("Mauritius") . "|Telecom Plus (Mauritius Telecom)" =>
+ {
+ provider_id => 'MU02',
+ url_tech => 'http://www.telecomplus.net',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ dnsServers => [ qw(202.123.1.6 202.123.1.11) ],
+ method => 'pppoa',
+ },
+
+ N("Morocco") . "|Maroc Telecom" =>
+ {
+ provider_id => 'MA01',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ dnsServers => [ qw(212.217.0.1 212.217.0.12) ],
+ method => 'pppoa',
+ },
+
+ N("Netherlands") . "|KPN" =>
+ {
+ provider_id => 'NL01',
+ vpi => 8,
+ vci => 30,
+ Encapsulation => 6,
+ method => 'pppoa',
+ },
+
+ N("Netherlands") . "|Eager Telecom" =>
+ {
+ provider_id => 'NL02',
+ vpi => 0,
+ vci => 21,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("Netherlands") . "|Tiscali" =>
+ {
+ provider_id => 'NL03',
+ vpi => 0,
+ vci => 22,
+ Encapsulation => 1,
+ method => 'pppoe',
+ },
+
+ N("Netherlands") . "|Versatel" =>
+ {
+ provider_id => 'NL04',
+ vpi => 0,
+ vci => 20,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("Norway") . "|Bluecom" =>
+ {
+ provider_id => 'NO01',
+ method => 'dhcp',
+ },
+
+ N("Norway") . "|Firstmile" =>
+ {
+ provider_id => 'NO02',
+ method => 'dhcp',
+ },
+
+ N("Norway") . "|NextGenTel" =>
+ {
+ provider_id => 'NO03',
+ method => 'dhcp',
+ },
+
+ N("Norway") . "|SSC" =>
+ {
+ provider_id => 'NO04',
+ method => 'dhcp',
+ },
+
+ N("Norway") . "|Tele2" =>
+ {
+ provider_id => 'NO05',
+ method => 'dhcp',
+ },
+
+ N("Norway") . "|Telenor ADSL" =>
+ {
+ provider_id => 'NO06',
+ method => 'PPPoE',
+ },
+
+ N("Norway") . "|Tiscali" =>
+ {
+ provider_id => 'NO07',
+ vpi => 8,
+ vci => 35,
+ method => 'dhcp',
+ },
+
+ N("Pakistan") . "|Micronet BroadBand" =>
+ {
+ provider_id => 'PK01',
+ vpi => 1,
+ vci => 20,
+ Encapsulation => 3,
+ dnsServers => [ qw(203.82.48.3 203.82.48.4) ],
+ method => 'pppoe',
+ encryption => 1,
+ },
+
+ N("Poland") . "|Telekomunikacja Polska (TPSA/neostrada)" =>
+ {
+ provider_id => 'PL01',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 6,
+ dnsServers => [ qw(194.204.152.34 217.98.63.164) ],
+ method => 'pppoa',
+ },
+
+ N("Poland") . "|Netia neostrada" =>
+ {
+ provider_id => 'PL02',
+ url_tech => 'http://www.netia.pl/?o=d&s=210',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 1,
+ dnsServers => [ qw(195.114.181.130 195.114.161.61) ],
+ method => 'pppoe',
+ },
+
+ N("Portugal") . "|PT" =>
+ {
+ provider_id => 'PT01',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 1,
+ method => 'pppoe',
+ },
+
+ N("Russia") . "|MTU-Intel" =>
+ {
+ provider_id => 'RU01',
+ url_tech => 'http://stream.ru/s-requirements',
+ vpi => 1,
+ vci => 32,
+ Encapsulation => 1,
+ dnsServers => [ qw(212.188.4.10 195.34.32.116) ],
+ method => 'pppoe',
+ },
+
+ N("Singapore") . "|Singnet" =>
+ {
+ provider_id => 'SG01',
+ vpi => 0,
+ vci => 64,
+ method => 'pppoa',
+ Encapsulation => 6,
+ },
+
+ N("Senegal") . "|Sonatel Multimedia Sentoo" =>
+ {
+ provider_id => 'SN01',
+ vpi => 0,
+ vci => 35,
+ Encapsulation => 6,
+ method => 'pppoa',
+ DOMAINNAME2 => 'sentoo.sn',
+ },
+
+ N("Slovenia") . "|SiOL" =>
+ {
+ provider_id => 'SL01',
+ vpi => 1,
+ vci => 20,
+ method => 'pppoe',
+ Encapsulation => 1,
+ dnsServers => [ qw(193.189.160.11 193.189.160.12) ],
+ DOMAINNAME2 => 'siol.net',
+ },
+
+ N("Spain") . "|Telefónica IP dinámica" =>
+ {
+ provider_id => 'ES01',
+ vpi => 8,
+ vci => 20,
+ Encapsulation => 1,
+ CMVep => 'ES',
+ dnsServers => [ qw(80.58.32.33 80.58.0.97) ],
+ method => 'pppoe',
+ login_format => 'adslppp@telefonicanetpa / adslppp',
+ },
+
+ N("Spain") . "|Telefónica ip fija" =>
+ {
+ provider_id => 'ES02',
+ vpi => 8,
+ vci => 20,
+ Encapsulation => 3,
+ CMVep => 'ES',
+ dnsServers => [ qw(80.58.32.33 80.58.0.97) ],
+ method => 'static',
+ login_format => 'adslppp@telefonicanetpa / adslppp',
+ },
+
+ N("Spain") . "|Wanadoo/Eresmas Retevision" =>
+ {
+ provider_id => 'ES03',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ CMVep => 'ES',
+ dnsServers => [ qw(80.58.0.33 80.58.32.97) ],
+ method => 'pppoa',
+ login_format => 'rtxxxxx@wanadooadsl',
+ encryption => 1,
+ },
+
+ N("Spain") . "|Wanadoo PPPoE" =>
+ {
+ provider_id => 'ES04',
+ vpi => 8,
+ vci => 20,
+ Encapsulation => 1,
+ CMVep => 'ES',
+ method => 'pppoe',
+ },
+
+ N("Spain") . "|Wanadoo ip fija" =>
+ {
+ provider_id => 'ES05',
+ vpi => 8,
+ vci => 20,
+ Encapsulation => 3,
+ CMVep => 'ES',
+ method => 'static',
+ },
+
+ N("Spain") . "|Tiscali" =>
+ {
+ provider_id => 'ES06',
+ vpi => 1,
+ vci => 20,
+ Encapsulation => 6,
+ CMVep => 'ES',
+ method => 'pppoa',
+ login_format => 'login@tiscali.es',
+ },
+
+ N("Spain") . "|Arrakis" =>
+ {
+ provider_id => 'ES07',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 6,
+ CMVep => 'ES',
+ method => 'pppoa',
+ },
+
+ N("Spain") . "|Auna" =>
+ {
+ provider_id => 'ES08',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 6,
+ CMVep => 'ES',
+ method => 'pppoa',
+ },
+
+ N("Spain") . "|Communitel" =>
+ {
+ provider_id => 'ES09',
+ vpi => 0,
+ vci => 21,
+ Encapsulation => 6,
+ CMVep => 'ES',
+ method => 'pppoa',
+ },
+
+ N("Spain") . "|Euskatel" =>
+ {
+ provider_id => 'ES10',
+ vpi => 8,
+ vci => 20,
+ Encapsulation => 1,
+ CMVep => 'ES',
+ method => 'pppoe',
+ },
+
+ N("Spain") . "|Uni2" =>
+ {
+ provider_id => 'ES11',
+ vpi => 1,
+ vci => 21,
+ Encapsulation => 6,
+ CMVep => 'ES',
+ method => 'pppoa',
+ },
+
+ N("Spain") . "|Ya.com PPPoE" =>
+ {
+ provider_id => 'ES12',
+ vpi => 8,
+ vci => 20,
+ Encapsulation => 1,
+ CMVep => 'ES',
+ method => 'pppoe',
+ login_format => 'adXXXXXXXXX@yacomadsl',
+ },
+
+ N("Spain") . "|Ya.com static" =>
+ {
+ provider_id => 'ES13',
+ vpi => 8,
+ vci => 20,
+ Encapsulation => 3,
+ CMVep => 'ES',
+ method => 'static',
+ login_format => 'adXXXXXXXXX@yacomadsl',
+ },
+
+ N("Spain") . "|Arsys" =>
+ {
+ provider_id => 'ES14',
+ vpi => 1,
+ vci => 21,
+ Encapsulation => 1,
+ CMVep => 'ES',
+ dnsServers => [ qw(217.76.128.4 217.76.129.4) ],
+ method => 'pppoe',
+ login_format => 'login@arsystel',
+ },
+
+ N("Spain") . "|Terra" =>
+ {
+ provider_id => 'ES15',
+ vpi => 8,
+ vci => 20,
+ Encapsulation => 1,
+ CMVep => 'ES',
+ dnsServers => [ qw(213.4.132.1 213.4.141.1) ],
+ method => 'pppoe',
+ login_format => 'login@terraadsl',
+ },
+
+ N("Spain") . "|Jazztel" =>
+ {
+ provider_id => 'ES16',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 6,
+ CMVep => 'ES',
+ dnsServers => [ qw(62.14.63.145 62.14.2.1) ],
+ method => 'pppoa',
+ login_format => 'username@adsl',
+ encryption => 1,
+ },
+
+ N("Sweden") . "|Telia" =>
+ {
+ provider_id => 'SE01',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("Switzerland") . "|" . N("Any") =>
+ {
+ provider_id => 'CH01',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 3,
+ method => 'pppoe',
+ },
+
+ N("Switzerland") . "|BlueWin / Swisscom" =>
+ {
+ provider_id => 'CH02',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 5,
+ dnsServers => [ qw(195.186.4.108 195.186.4.109) ],
+ method => 'pppoa',
+ },
+
+ N("Switzerland") . "|VTX Datacomm (ex-Tiscali)" =>
+ {
+ provider_id => 'CH03',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 1,
+ method => 'pppoa',
+ },
+
+ N("Thailand") . "|Asianet" =>
+ {
+ provider_id => 'TH01',
+ vpi => 0,
+ vci => 64,
+ Encapsulation => 1,
+ dnsServers => [ qw(203.144.225.242 203.144.225.72 203.144.223.66) ],
+ method => 'pppoe',
+ },
+
+ N("Tunisia") . "|Planet.tn" =>
+ {
+ provider_id => 'TU01',
+ url_tech => 'http://www.planet.tn/',
+ vpi => 0,
+ vci => 23,
+ Encapsulation => 5,
+ dnsServers => [ qw(193.95.93.77 193.95.66.10) ],
+ method => 'pppoe',
+ },
+
+ N("Turkey") . "|TTnet" =>
+ {
+ provider_id => 'TR01',
+ url_tech => 'http://www.ttnet.net.tr',
+ vpi => 8,
+ vci => 23,
+ Encapsulation => 1,
+ dnsServers => [ qw(195.175.37.14 195.175.37.69) ],
+ method => 'pppoe',
+ encryption => 1,
+ login_format => 'login@ttnet',
+ },
+
+ N("United Arab Emirates") . "|Etisalat" =>
+ {
+ provider_id => 'AE01',
+ vpi => 0,
+ vci => 32,
+ Encapsulation => 5,
+ dnsServers => [ qw(213.42.20.20 195.229.241.222) ],
+ method => 'pppoa',
+ },
+
+ N("United Kingdom") . "|Tiscali UK " =>
+ {
+ provider_id => 'UK01',
+ vpi => 0,
+ vci => 26,
+ Encapsulation => 6,
+ dnsServers => [ qw(212.74.112.66 212.74.112.67) ],
+ method => 'pppoa',
+ },
+
+ N("United Kingdom") . "|British Telecom " =>
+ {
+ provider_id => 'UK02',
+ vpi => 0,
+ vci => 26,
+ Encapsulation => 6,
+ dnsServers => [ qw(194.74.65.69 194.72.9.38) ],
+ method => 'pppoa',
+ },
+
+ );
+
+1;
diff --git a/lib/network/connection/wireless.pm b/lib/network/connection/wireless.pm
new file mode 100644
index 0000000..ad02481
--- /dev/null
+++ b/lib/network/connection/wireless.pm
@@ -0,0 +1,1132 @@
+package network::connection::wireless;
+
+use base qw(network::connection::ethernet);
+
+use strict;
+use common;
+use log;
+use network::network;
+
+#- class attributes:
+#- network: ID of the selected network
+
+sub get_type_name() { N("Wireless") }
+sub get_type_description() { N("Wireless (Wi-Fi)") }
+sub _get_type_icon() { 'wireless' }
+sub get_devices {
+ my ($_class, %options) = @_;
+ require detect_devices;
+ my @devices = detect_devices::probe_category('network/wireless');
+ my @wireless = grep { detect_devices::is_wireless_interface($_) } detect_devices::get_lan_interfaces();
+ my @all_devices = (@devices, network::connection::ethernet::get_unlisted_devices(\@wireless, \@devices));
+ foreach (@all_devices) {
+ my $interface = $_->{interface} || network::connection::ethernet::device_to_interface($_) or next;
+ my $driver = network::connection::ethernet::interface_to_driver($interface) or next;
+ $_->{driver} = $driver if $driver;
+ }
+ @all_devices,
+ if_(!$options{automatic_only}, {
+ driver => 'ndiswrapper',
+ description => N("Use a Windows driver (with ndiswrapper)"),
+ });
+}
+
+sub handles_ifcfg {
+ my ($_class, $ifcfg) = @_;
+ require detect_devices;
+ detect_devices::is_wireless_interface($ifcfg->{DEVICE}) || exists $ifcfg->{WIRELESS_MODE};
+}
+
+sub get_metric { 35 }
+
+#- http://www.linux-wireless.org/Install-HOWTO/WL/WEP-Key-HOWTO.txt
+my $wpa_supplicant_max_wep_key_len = 32;
+
+our %wireless_enc_modes = (
+ none => N_("None"),
+ open => N_("Open WEP"),
+ restricted => N_("Restricted WEP"),
+ 'wpa-psk' => N_("WPA/WPA2 Pre-Shared Key"),
+ 'wpa-eap' => N_("WPA/WPA2 Enterprise"),
+);
+#define the eap related variables we handle
+#0 means we preserve value if found
+#1 means we save without quotes
+#2 save with quotes
+my %eap_vars = (
+ ssid => 2,
+ scan_ssid => 1,
+ identity => 2,
+ password => 2,
+ key_mgmt => 1,
+ eap => 1,
+ pairwise => 1,
+ group => 1,
+ proto => 1,
+ ca_cert => 2,
+ client_cert => 2,
+ phase2 => 2,
+ anonymous_identity => 2,
+ subject_match => 2,
+ disabled => 0,
+ id_str => 0,
+ bssid => 0,
+ priority => 0,
+ auth_alg => 0,
+ eapol_flags => 0,
+ proactive_key_caching => 0,
+ peerkey => 0,
+ ca_path => 0,
+ private_key => 0,
+ private_key_passwd => 0,
+ dh_file => 0,
+ altsubject_match => 0,
+ phase1 => 0,
+ fragment_size => 0,
+ eap_workaround => 0,
+);
+
+my @thirdparty_settings = (
+ {
+ name => 'zd1201',
+ description => 'ZyDAS ZD1201',
+ url => 'http://linux-lc100020.sourceforge.net/',
+ firmware => {
+ test_file => 'zd1201*.fw',
+ },
+ },
+
+ (map {
+ {
+ name => "ipw${_}",
+ description => "Intel(R) PRO/Wireless ${_}",
+ url => "http://ipw${_}.sourceforge.net/",
+ firmware => {
+ url => "http://ipw${_}.sourceforge.net/firmware.php",
+ test_file => "ipw$_-*.fw",
+ },
+ };
+ } (2100, 2200)),
+
+ {
+ name => "ipw3945",
+ description => "Intel(R) PRO/Wireless 3945",
+ url => "http://ipw3945.sourceforge.net/",
+ firmware => {
+ package => "ipw3945-ucode",
+ test_file => "ipw3945.ucode",
+ },
+ tools => {
+ package => "ipw3945d",
+ test_file => '/usr/sbin/ipw3945d',
+ },
+ },
+
+ (map {
+ my ($version, $ucode_api, $ucode_version) = @$_;
+ $ucode_version ||= $version;
+ {
+ name => "iwl${version}",
+ description => "Intel(R) PRO/Wireless ${version}",
+ url => "http://intellinuxwireless.org/",
+ firmware => {
+ package => "iwlwifi-${version}-ucode",
+ test_file => "iwlwifi-${ucode_version}${ucode_api}.ucode",
+ },
+ sleep => 1,
+ };
+ } ([ 3945, '-1' ], [ 4965, '-1' ], [ 'agn', '-1', 5000 ])),
+
+ {
+ name => 'p54pci',
+ description => 'PCI adaptors based on the Intersil Prism54 chip series',
+ url => 'http://wireless.kernel.org/en/users/Drivers/p54',
+ firmware => {
+ url => 'http://wireless.kernel.org/en/users/Drivers/p54#firmware',
+ test_file => "isl3886pci",
+ },
+ },
+
+ {
+ name => 'p54usb',
+ description => 'USB adaptors based on the Intersil Prism54 chip series',
+ url => 'http://wireless.kernel.org/en/users/Drivers/p54',
+ firmware => {
+ url => 'http://wireless.kernel.org/en/users/Drivers/p54#firmware',
+ test_file => "isl388*usb",
+ },
+ },
+
+ {
+ name => 'atmel',
+ matching => [ qw(at76_usb atmel_cs atmel_pci) ],
+ description => 'Atmel at76c50x cards',
+ url => 'http://thekelleys.org.uk/atmel/',
+ firmware => {
+ test_file => 'atmel_at76c50*',
+ },
+ links => 'http://at76c503a.berlios.de/',
+ },
+
+ {
+ name => 'madwifi',
+ matching => 'ath_pci',
+ description => 'Multiband Atheros Driver for WiFi',
+ url => 'http://madwifi.org/',
+ kernel_module => 1,
+ tools => {
+ optional => 1,
+ test_file => '/usr/bin/athstats',
+ },
+ },
+
+ {
+ name => 'prism2',
+ matching => qr/^prism2_/,
+ description => 'Prism2 based cards',
+ tools => {
+ package => 'prism2-utils',
+ test_file => '/sbin/wlanctl-ng',
+ },
+ },
+
+ {
+ name => 'zd1211',
+ matching => 'zd1211rw',
+ description => 'ZD1211 chip',
+ firmware => {
+ url => 'http://sourceforge.net/projects/zd1211/',
+ test_file => 'zd1211/zd1211_*',
+ },
+ },
+
+ {
+ name => 'bcm43xx',
+ description => 'Broadcom bcm43xx wireless chips',
+ url => 'http://bcm43xx.berlios.de/',
+ firmware => {
+ test_file => 'bcm43xx_microcode*.fw',
+ no_package => 1,
+ extract => {
+ name => 'bcm43xx-fwcutter',
+ test_file => '/usr/bin/bcm43xx-fwcutter',
+ windows_source => 'bcmwl5.sys',
+ default_source => 'bcmwl5.sys',
+ run => sub {
+ my ($file) = @_;
+ run_program::rooted($::prefix, '/usr/bin/bcm43xx-fwcutter',
+ '-w', $network::thirdparty::firmware_directory, $file);
+ },
+ },
+ },
+ },
+
+ (map {
+ +{
+ name => $_,
+ description => "Broadcom $_ wireless chips",
+ url => 'http://wireless.kernel.org/en/users/Drivers/b43',
+ firmware => {
+ test_file => $_ . "/ucode*.fw",
+ no_package => 1,
+ extract => {
+ name => 'b43-fwcutter',
+ test_file => '/usr/bin/b43-fwcutter',
+ windows_source => 'bcmwl5.sys',
+ default_source => 'bcmwl5.sys',
+ run => sub {
+ my ($file) = @_;
+ run_program::rooted($::prefix, '/usr/bin/b43-fwcutter',
+ '-w', $network::thirdparty::firmware_directory, $file);
+ },
+ },
+ },
+ };
+ } qw(b43 b43legacy)),
+
+ {
+ name => 'broadcom-wl',
+ matching => 'wl',
+ description => 'Broadcom Hybrid',
+ url => 'http://www.broadcom.com/support/802.11/linux_sta.php',
+ kernel_module => 1,
+ },
+
+ {
+ name => 'acx100',
+ matching => [ qw(acx_pci acx_usb) ],
+ description => 'ACX100/ACX111/TNETW1450',
+ firmware => {
+ url => 'http://acx100.sourceforge.net/wiki/Firmware',
+ test_file => 'tiacx1*',
+ no_distro_package => 1,
+ },
+ },
+
+ {
+ name => 'ndiswrapper',
+ description => 'Wireless device using ndiswrapper (windows drivers)',
+ tools => {
+ test_file => '/usr/sbin/ndiswrapper',
+ },
+ firmware => {
+ user_install => sub {
+ my ($settings, $in) = @_;
+ require network::ndiswrapper;
+ $settings->{device} = network::ndiswrapper::select_device($in) or return;
+ network::ndiswrapper::setup_device($in, $settings->{device});
+ $settings->{device}{driver} = $settings->{name};
+ },
+ url => 'http://ndiswrapper.sourceforge.net/mediawiki/index.php/List',
+ component_name => N_("Windows driver"),
+ no_package => 1,
+ },
+ no_module_reload => 1,
+ },
+
+ {
+ name => 'rt61',
+ matching => 'rt61pci',
+ description => 'Ralink RT61 802.11abg WLAN',
+ firmware => {
+ url => 'http://rt2x00.serialmonkey.com/',
+ test_file => 'rt2661.bin',
+ },
+ },
+
+ {
+ name => 'rt73',
+ matching => 'rt73usb',
+ description => 'Ralink RT73 802.11abg WLAN',
+ firmware => {
+ url => 'http://rt2x00.serialmonkey.com/',
+ test_file => 'rt73.bin',
+ },
+ },
+
+ (map {
+ +{
+ name => "rt${_}",
+ matching => qr/^rt${_}(sta|)$/,
+ description => 'Ralink RT${_} WiFi',
+ kernel_module => 1,
+ firmware => {
+ url => 'http://www.ralinktech.com/',
+ test_file => "rt${_}.bin",
+ },
+ };
+ } (2860, 2870, 3090)),
+
+ {
+ name => 'rtl8187se',
+ matching => 'r8180',
+ description => 'Realtek RTL8180 / RTL8185 WiFi',
+ kernel_module => 1,
+ },
+);
+
+sub get_packages { 'wireless-tools' }
+
+sub get_thirdparty_settings() {
+ \@thirdparty_settings;
+}
+
+sub setup_thirdparty {
+ my ($self, $in) = @_;
+ require network::rfswitch;
+ network::rfswitch::configure();
+ if ($self->get_driver eq 'ndiswrapper') {
+ require network::ndiswrapper;
+ my @devices = map { network::ndiswrapper::present_devices($_) } network::ndiswrapper::installed_drivers();
+ return {} if member($self->{device}, @devices) && network::ndiswrapper::find_interface($self->{device});
+ }
+ my $thirdparty = $self->SUPER::setup_thirdparty($in);
+ my $driver = $self->get_driver;
+ if ($self->{thirdparty} && $driver eq 'ipw3945' && !$self->rf_killed && !$self->SUPER::check_device) {
+ log::explanations("Reloading module $driver");
+ eval { modules::unload($driver) };
+ eval { modules::load($driver) };
+ }
+ $thirdparty;
+}
+
+sub rf_killed {
+ my ($self) = @_;
+ if ($self->{device}{sysfs_device}) {
+ my $rf_kill_path = $self->{device}{sysfs_device} . "/rf_kill";
+ if (-e $rf_kill_path) {
+ my $rf_kill = chomp_(cat_($rf_kill_path));
+ #- for ipw drivers, 0 means no RF kill switch
+ return $rf_kill != 0;
+ }
+ }
+ undef;
+}
+
+sub check_device {
+ my ($self) = @_;
+ if ($self->rf_killed) {
+ $self->{device}{error} = N("Your wireless card is disabled, please enable the wireless switch (RF kill switch) first.");
+ return 0;
+ }
+ return $self->SUPER::check_device;
+}
+
+sub load_interface_settings {
+ my ($self) = @_;
+ $self->network::connection::load_interface_settings;
+ $self->{hide_passwords} = 1;
+ # override ifcfg with network-specific settings if available
+ my $network = $self->get_selected_network;
+ $self->{ifcfg}= $network ?
+ get_network_ifcfg($network->{ap}) || get_network_ifcfg($network->{essid}) :
+ $self->{ifcfg};
+
+ $self->SUPER::map_ifcfg2config_settings;
+}
+
+sub get_networks {
+ my ($self, $o_net) = @_;
+ require network::monitor;
+ ($self->{networks}, $self->{control}{roaming}) = network::monitor::list_wireless($o_net && $o_net->{monitor}, $self->get_interface);
+ $self->probed_networks;
+ $self->{networks};
+}
+
+sub refresh_roaming_ids {
+ my ($self) = @_;
+ #- needed when switching from non-roaming to roaming
+ #- or after restarting wpa_supplicant
+ #- to get fresh wpa_supplicant network IDs
+ get_networks($self) if $self->{control}{roaming};
+}
+
+sub selected_network_is_configured {
+ my ($self) = @_;
+ $self->refresh_roaming_ids;
+ $self->SUPER::selected_network_is_configured;
+}
+
+sub guess_network {
+ my ($_self) = @_;
+ #- FIXME: try to find the AP matching $self->{ifcfg}{WIRELESS_ESSID};
+}
+
+sub get_network_ifcfg {
+ my ($ssid) = @_;
+ require network::network;
+ my $file = $::prefix . $network::network::wireless_d . '/' . $ssid;
+ -f $file && { getVarsFromSh($file) };
+}
+
+sub guess_network_access_settings {
+ my ($self) = @_;
+
+ my $network = $self->get_selected_network;
+ my $ifcfg = $self->{ifcfg};
+ $ifcfg ||= {};
+
+ $self->{access}{network}{bssid} = $network && $network->{hidden} && $network->{ap};
+ $self->{access}{network}{essid} = $network && $network->{essid} || $ifcfg->{WIRELESS_ESSID} || !$network && "any";
+ ($self->{access}{network}{key}, my $restricted, $self->{access}{network}{force_ascii_key}) =
+ get_wep_key_from_iwconfig($ifcfg->{WIRELESS_ENC_KEY});
+
+ $self->{access}{network}{encryption} =
+ $network && $network->{flags} =~ /eap/i ?
+ 'wpa-eap' :
+ $network && $network->{flags} =~ /wpa/i ?
+ 'wpa-psk' :
+ $network && $network->{flags} =~ /wep/i || $self->{access}{network}{key} ?
+ $ifcfg->{WIRELESS_ENC_MODE} || ($restricted ? 'restricted' : 'open') :
+ 'none';
+
+ undef $self->{ifcfg}{WIRELESS_IWPRIV} if is_old_rt2x00($self->get_driver) && $self->{ifcfg}{WIRELESS_IWPRIV} =~ /WPAPSK/;
+
+ my $system_file = '/etc/sysconfig/drakx-net';
+ my %global_settings = getVarsFromSh($system_file);
+ $self->{control}{roaming} =
+ (exists $self->{ifcfg}{WIRELESS_WPA_DRIVER} || text2bool($global_settings{ROAMING}))
+ && !is_old_rt2x00($self->get_driver);
+
+ $self->{access}{network}{mode} =
+ $network && $network->{mode} ||
+ $ifcfg->{WIRELESS_MODE} ||
+ 'Managed';
+
+ wpa_supplicant_load_eap_settings($self->{access}{network}) if $self->need_wpa_supplicant;
+}
+
+sub get_network_access_settings_label { N("Wireless settings") }
+
+sub get_network_access_settings {
+ my ($self) = @_;
+ [
+ { label => N("Operating Mode"), val => \$self->{access}{network}{mode},
+ list => [ N_("Ad-hoc"), N_("Managed"), N_("Master"), N_("Repeater"), N_("Secondary"), N_("Auto") ],
+ format => \&translate,
+ },
+ { label => N("Network name (ESSID)"), val => \$self->{access}{network}{essid},
+ disabled => sub { my $network = $self->get_selected_network; $network && $network->{essid} } },
+ { label => N("Encryption mode"), val => \$self->{access}{network}{encryption}, list => [ keys %wireless_enc_modes ],
+ sort => 1, format => sub { translate($wireless_enc_modes{$_[0]}) } },
+ { label => N("Encryption key"), val => \$self->{access}{network}{key},
+ hidden => sub { $self->{hide_passwords} },
+ disabled => sub { member($self->{access}{network}{encryption}, qw(none wpa-eap)) } },
+ { text => N("Hide password"),
+ type => "bool", val => \$self->{hide_passwords} },
+ { text => N("Force using this key as ASCII string (e.g. for Livebox)"),
+ type => "bool", val => \$self->{access}{network}{force_ascii_key},
+ disabled => sub {
+ #- only for WEP keys looking like hexadecimal
+ !member($self->{access}{network}{encryption}, qw(open restricted)) ||
+ !get_hex_key($self->{access}{network}{key});
+ } },
+ { label => N("EAP Login/Username"), val => \$self->{access}{network}{eap_identity},
+ disabled => sub { $self->{access}{network}{encryption} ne 'wpa-eap' },
+ help => N("The login or username. Format is plain text. If you
+need to specify domain then try the untested syntax
+ DOMAIN\\username") },
+ { label => N("EAP Password"), val => \$self->{access}{network}{eap_password},
+ hidden => sub { $self->{hide_passwords} },
+ disabled => sub { $self->{access}{network}{encryption} ne 'wpa-eap' },
+ help => N(" Password: A string.
+Note that this is not the same thing as a psk.
+____________________________________________________
+RELATED ADDITIONAL INFORMATION:
+In the Advanced Page, you can select which EAP mode
+is used for authentication. For the eap mode setting
+ Auto Detect: implies all possible modes are tried.
+
+If Auto Detect fails, try the PEAP TTLS combo bofore others
+Note:
+ The settings MD5, MSCHAPV2, OTP and GTC imply
+automatically PEAP and TTLS modes.
+ TLS mode is completely certificate based and may ignore
+the username and password values specified here.") },
+ { label => N("EAP client certificate"), val => \$self->{access}{network}{eap_client_cert},
+ disabled => sub { $self->{access}{network}{encryption} ne 'wpa-eap' },
+ help => N("The complete path and filename of client certificate. This is
+only used for EAP certificate based authentication. It could be
+considered as the alternative to username/password combo.
+ Note: other related settings are shown on the Advanced page.") },
+ { label => N("Network ID"), val => \$self->{ifcfg}{WIRELESS_NWID}, advanced => 1 },
+ { label => N("Operating frequency"), val => \$self->{ifcfg}{WIRELESS_FREQ}, advanced => 1 },
+ { label => N("Sensitivity threshold"), val => \$self->{ifcfg}{WIRELESS_SENS}, advanced => 1 },
+ { label => N("Bitrate (in b/s)"), val => \$self->{ifcfg}{WIRELESS_RATE}, advanced => 1 },
+ { label => N("RTS/CTS"), val => \$self->{ifcfg}{WIRELESS_RTS}, advanced => 1,
+ help => N("RTS/CTS adds a handshake before each packet transmission to make sure that the
+channel is clear. This adds overhead, but increase performance in case of hidden
+nodes or large number of active nodes. This parameter sets the size of the
+smallest packet for which the node sends RTS, a value equal to the maximum
+packet size disable the scheme. You may also set this parameter to auto, fixed
+or off.")
+ },
+ { label => N("Fragmentation"), val => \$self->{ifcfg}{WIRELESS_FRAG}, advanced => 1 },
+ { label => N("iwconfig command extra arguments"), val => \$self->{ifcfg}{WIRELESS_IWCONFIG}, advanced => 1,
+ help => N("Here, one can configure some extra wireless parameters such as:
+ap, channel, commit, enc, power, retry, sens, txpower (nick is already set as the hostname).
+
+See iwconfig(8) man page for further information."),
+ },
+ { label =>
+ #-PO: split the "xyz command extra argument" translated string into two lines if it's bigger than the english one
+ N("iwspy command extra arguments"), val => \$self->{ifcfg}{WIRELESS_IWSPY}, advanced => 1,
+ help => N("iwspy is used to set a list of addresses in a wireless network
+interface and to read back quality of link information for each of those.
+
+This information is the same as the one available in /proc/net/wireless :
+quality of the link, signal strength and noise level.
+
+See iwpspy(8) man page for further information."),
+ },
+ { label => N("iwpriv command extra arguments"), val => \$self->{ifcfg}{WIRELESS_IWPRIV}, advanced => 1,
+ disabled => sub { $self->need_rt2x00_iwpriv },
+ help => N("iwpriv enable to set up optionals (private) parameters of a wireless network
+interface.
+
+iwpriv deals with parameters and setting specific to each driver (as opposed to
+iwconfig which deals with generic ones).
+
+In theory, the documentation of each device driver should indicate how to use
+those interface specific commands and their effect.
+
+See iwpriv(8) man page for further information."),
+ },
+ { label => N("EAP Protocol"), val => \$self->{access}{network}{forceeap},
+ list => [ N_("Auto Detect"), N_("WPA2"), N_("WPA") ],
+ sort => 1, format => \&translate, advanced => 1,
+ help => N("Auto Detect is recommended as it first tries WPA version 2 with
+a fallback to WPA version 1") },
+ { label => N("EAP Mode"), val => \$self->{access}{network}{eap_eap},
+ list => [ N_("Auto Detect"), N_("PEAP"), N_("TTLS"), N_("TLS"), N_("MSCHAPV2"), N_("MD5"), N_("OTP"), N_("GTC"), N_("LEAP") , N_("PEAP TTLS"), N_("TTLS TLS") ],
+ sort => 1, format => \&translate, advanced => 1, },
+ { label => N("EAP key_mgmt"), val => \$self->{access}{network}{eap_key_mgmt}, advanced => 1,
+ disabled => sub { $self->{access}{network}{encryption} ne 'wpa-eap' },
+ help => N("list of accepted authenticated key management protocols.
+possible values are WPA-EAP, IEEE8021X, NONE") },
+ { label => N("EAP outer identity"), val => \$self->{access}{network}{eap_anonymous_identity}, advanced => 1,
+ disabled => sub { $self->{access}{network}{encryption} ne 'wpa-eap' },
+ help => N("Anonymous identity string for EAP: to be used as the
+unencrypted identity with EAP types that support different
+tunnelled identity, e.g., TTLS") },
+ { label => N("EAP phase2"), val => \$self->{access}{network}{eap_phase2}, advanced => 1,
+ disabled => sub { $self->{access}{network}{encryption} ne 'wpa-eap' } ,
+ help => N("Inner authentication with TLS tunnel parameters.
+input is string with field-value pairs, Examples:
+auth=MSCHAPV2 for PEAP or
+autheap=MSCHAPV2 autheap=MD5 for TTLS") },
+ { label => N("EAP CA certificate"), val => \$self->{access}{network}{eap_ca_cert}, advanced => 1,
+ disabled => sub { $self->{access}{network}{encryption} ne 'wpa-eap' },
+ help => N("Full file path to CA certificate file (PEM/DER). This file
+can have one or more trusted CA certificates. If ca_cert are not
+included, server certificate will not be verified. If possible,
+a trusted CA certificate should always be configured
+when using TLS or TTLS or PEAP.") },
+ { label => N("EAP certificate subject match"), val => \$self->{access}{network}{eap_subject_match}, advanced => 1,
+ disabled => sub { $self->{access}{network}{encryption} ne 'wpa-eap' },
+ help => N(" Substring to be matched against the subject of
+the authentication server certificate. If this string is set,
+the server sertificate is only accepted if it contains this
+string in the subject. The subject string is in following format:
+/C=US/ST=CA/L=San Francisco/CN=Test AS/emailAddress=as\@example.com") },
+ { label => N("Extra directives"), val => \$self->{access}{network}{extra}, advanced => 1,
+ help => N("Here one can pass extra settings to wpa_supplicant
+The expected format is a string field=value pair. Multiple values
+maybe specified, separating each value with the # character.
+Note: directives are passed unchecked and may cause the wpa
+negotiation to fail silently. Supported directives are preserved
+across editing.
+Supported directives are :
+ disabled, id_str, bssid, priority, auth_alg, eapol_flags,
+ proactive_key_caching, peerkey, ca_path, private_key,
+ private_key_passwd, dh_file, altsubject_match, phase1,
+ fragment_size and eap_workaround, pairwise, group
+ Others such as key_mgmt, eap maybe used to force
+ special settings different from the U.I settings.") },
+ ];
+}
+
+sub check_network_access_settings {
+ my ($self) = @_;
+
+ if (!member($self->{access}{network}{encryption}, qw(none wpa-eap)) && !$self->{access}{network}{key}) {
+ $self->{network_access}{error}{message} = N("An encryption key is required.");
+ $self->{network_access}{error}{field} = \$self->{access}{network}{key};
+ return 0;
+ }
+
+ if ($self->{access}{network}{encryption} eq 'wpa-psk' &&
+ !convert_psk_key_for_wpa_supplicant($self->{access}{network}{key})) {
+ $self->{network_access}{error}{message} = N("The pre-shared key should have between 8 and 63 ASCII characters, or 64 hexadecimal characters.");
+ $self->{network_access}{error}{field} = \$self->{access}{network}{key};
+ return 0;
+ }
+ if (member($self->{access}{network}{encryption}, qw(open restricted)) &&
+ !convert_wep_key_for_wpa_supplicant($self->{access}{network}{key}, $self->{access}{network}{force_ascii_key})) {
+ $self->{network_access}{error}{message} = N("The WEP key should have at most %d ASCII characters or %d hexadecimal characters.",
+ $wpa_supplicant_max_wep_key_len, $wpa_supplicant_max_wep_key_len * 2);
+ $self->{network_access}{error}{field} = \$self->{access}{network}{key};
+ return 0;
+ }
+
+ if ($self->{ifcfg}{WIRELESS_FREQ} && $self->{ifcfg}{WIRELESS_FREQ} !~ /[0-9.]*[kGM]/) {
+ $self->{network_access}{error}{message} = N("Freq should have the suffix k, M or G (for example, \"2.46G\" for 2.46 GHz frequency), or add enough '0' (zeroes).");
+ $self->{network_access}{error}{field} = \$self->{ifcfg}{WIRELESS_FREQ};
+ return 0;
+ }
+
+ if ($self->{ifcfg}{WIRELESS_RATE} && $self->{ifcfg}{WIRELESS_RATE} !~ /[0-9.]*[kGM]/) {
+ $self->{network_access}{error}{message} = N("Rate should have the suffix k, M or G (for example, \"11M\" for 11M), or add enough '0' (zeroes).");
+ $self->{network_access}{error}{field} = \$self->{ifcfg}{WIRELESS_RATE};
+ return 0;
+ }
+
+ return 1;
+}
+
+sub get_control_settings {
+ my ($self) = @_;
+ [
+ @{$self->SUPER::get_control_settings},
+ { text => N("Allow access point roaming"), val => \$self->{control}{roaming}, type => "bool",
+ disabled => sub { is_wpa_supplicant_blacklisted($self->get_driver) } },
+ ];
+}
+
+sub need_wpa_supplicant {
+ my ($self) = @_;
+ ($self->{control}{roaming} || $self->{access}{network}{encryption} =~ /^wpa-/) && !is_old_rt2x00($self->get_driver);
+}
+
+sub install_packages {
+ my ($self, $in) = @_;
+ if ($self->need_wpa_supplicant) {
+ $in->do_pkgs->ensure_is_installed('wpa_supplicant', '/usr/sbin/wpa_supplicant') or return;
+ $in->do_pkgs->ensure_is_installed('mandi', '/usr/sbin/mandi');
+ }
+ $self->SUPER::install_packages($in);
+}
+
+
+sub build_ifcfg_settings {
+ my ($self) = @_;
+
+ # if we are not using WEP, the key is always ASCII (#52128)
+ $self->{access}{network}{force_ascii_key} = 1 unless member($self->{access}{network}{encryption}, qw(open restricted));
+
+ my $settings = {
+ WIRELESS_MODE => $self->{access}{network}{mode},
+ if_($self->need_wpa_supplicant,
+ WIRELESS_WPA_DRIVER => wpa_supplicant_get_driver($self->get_driver),
+ WIRELESS_WPA_REASSOCIATE => bool2yesno($self->need_wpa_supplicant_reassociate),
+ MII_NOT_SUPPORTED => 'no',
+ ),
+ WIRELESS_ESSID => $self->{access}{network}{essid},
+ if_($self->{access}{network}{encryption} ne 'none',
+ WIRELESS_ENC_KEY => convert_wep_key_for_iwconfig($self->{access}{network}{key}, $self->{access}{network}{force_ascii_key})),
+ if_(member($self->{access}{network}{encryption}, qw(open restricted)),
+ WIRELESS_ENC_MODE => $self->{access}{network}{encryption}),
+ if_($self->need_rt2x00_iwpriv,
+ #- use iwpriv for WPA with rt2400/rt2500 drivers, they don't plan to support wpa_supplicant
+ WIRELESS_IWPRIV => qq(set AuthMode=WPAPSK
+set EncrypType=TKIP
+set SSID=$self->{access}{network}{essid}
+set WPAPSK="$self->{access}{network}{key}"
+set TxRate=0)),
+ (map { $_ => $self->{ifcfg}{$_} }
+ qw(WIRELESS_NWID WIRELESS_FREQ WIRELESS_SENS WIRELESS_RATE WIRELESS_RTS WIRELESS_FRAG WIRELESS_IWCONFIG WIRELESS_IWSPY), if_(!$self->need_rt2x00_iwpriv, 'WIRELESS_IWPRIV')),
+ };
+ $self->SUPER::build_ifcfg_settings($settings);
+}
+
+sub add_network_to_wpa_supplicant {
+ my ($self) = @_;
+ if ($self->{access}{network}{encryption} eq 'wpa-eap') {
+ wpa_supplicant_add_eap_network($self->{access}{network});
+ } else {
+ wpa_supplicant_add_network($self->{access}{network});
+ }
+ #- this should be handled by the monitoring daemon instead
+ run_program::run('/usr/sbin/wpa_cli', 'reconfigure');
+}
+
+sub write_settings {
+ my ($self, $o_net, $o_modules_conf) = @_;
+
+ my $network = $self->get_selected_network;
+ network::network::write_wireless_conf($_, $self->build_ifcfg_settings) foreach
+ grep { $_ } ($network ? $network->{ap} : ()), $self->{access}{network}{essid};
+
+ $self->add_network_to_wpa_supplicant if $self->need_wpa_supplicant;
+
+ wlan_ng_configure($self->{access}{network}{essid}, $self->{access}{network}{key}, $self->get_interface, $self->get_driver) if $self->{thirdparty}{name} eq 'prism2';
+
+ $self->SUPER::write_settings($o_net, $o_modules_conf);
+}
+
+sub apply_network_selection {
+ my ($self) = @_;
+ require network::network;
+ my $file = network::network::get_ifcfg_file($self->get_interface);
+ network::network::write_interface_settings($self->build_ifcfg_settings, $file);
+
+ $self->add_network_to_wpa_supplicant if $self->need_wpa_supplicant;
+}
+
+sub network_is_configured {
+ my ($self, $network) = @_;
+ if ($self->{control}{roaming}) {
+ return defined $network->{id};
+ } else {
+ my $wireless_ifcfg = get_network_ifcfg($network->{ap}) || defined $network->{essid} && get_network_ifcfg($network->{essid});
+ return $wireless_ifcfg;
+ }
+}
+
+sub connect {
+ my ($self, $_in, $net) = @_;
+
+ $self->SUPER::connect;
+
+ if ($self->{control}{roaming}) {
+ my $network_id;
+ foreach (0 .. 1) {
+ $self->refresh_roaming_ids if $_;
+ my $network = $self->get_selected_network;
+ $network_id = $network->{id} if $network && defined $network->{id};
+ }
+ if (defined $network_id) {
+ if ($net->{monitor}) {
+ log::explanations("selecting wpa_supplicant network $network_id through network monitor");
+ eval { $net->{monitor}->select_network($network_id) };
+ return !$@;
+ } else {
+ run_program::run('/usr/sbin/wpa_cli', 'select_network', $network_id);
+ }
+ }
+ }
+}
+
+sub get_status_message {
+ my ($self, $status) = @_;
+ my $interface = $self->get_interface;
+ my ($current_essid, $current_ap) = get_access_point($interface);
+ my $network = $current_essid || $current_ap && "[$current_ap]";
+ {
+ link_up => N("Associated to wireless network \"%s\" on interface %s", $network, $interface),
+ link_down => N("Lost association to wireless network on interface %s", $interface),
+ }->{$status} || $self->SUPER::get_status_message($status);
+}
+
+
+
+my $wpa_supplicant_conf = "/etc/wpa_supplicant.conf";
+
+sub get_access_point {
+ my ($intf) = @_;
+ (chomp_(`/sbin/iwgetid -r $intf 2>/dev/null`), lc(chomp_(`/sbin/iwgetid -r -a $intf 2>/dev/null`)));
+}
+
+sub is_old_rt2x00 {
+ my ($module) = @_;
+ member($module, qw(rt2400 rt2500 rt2570 rt61 rt73));
+}
+
+sub is_wpa_supplicant_blacklisted {
+ my ($module) = @_;
+ is_old_rt2x00($module);
+}
+
+sub need_wpa_supplicant_reassociate {
+ my ($self) = @_;
+ $self->get_driver eq 'rt61pci';
+}
+
+sub need_rt2x00_iwpriv {
+ my ($self) = @_;
+ is_old_rt2x00($self->get_driver) && $self->{access}{network}{encryption} eq 'wpa-psk';
+}
+
+sub get_hex_key {
+ my ($key) = @_;
+ #- odd number or non-hexa characters, consider the key as ASCII and prepend "s:"
+ if ($key =~ /^([[:xdigit:]]{4}[\:-]?)+[[:xdigit:]]{2,}$/) {
+ $key =~ s/[\:-]//g;
+ return lc($key);
+ }
+}
+
+sub convert_wep_key_for_iwconfig {
+ my ($real_key, $force_ascii) = @_;
+ !$force_ascii && get_hex_key($real_key) || "s:$real_key";
+}
+
+sub convert_wep_key_for_wpa_supplicant {
+ my ($key, $force_ascii) = @_;
+ if (my $hex_key = !$force_ascii && get_hex_key($key)) {
+ return length($hex_key) <= $wpa_supplicant_max_wep_key_len * 2 && $hex_key;
+ } else {
+ return length($key) <= $wpa_supplicant_max_wep_key_len && qq("$key");
+ }
+}
+
+sub get_wep_key_from_iwconfig {
+ my ($key) = @_;
+ my ($mode, $real_key) = $key =~ /^(?:(open|restricted)\s+)?(.*)$/;
+ my $is_ascii = $real_key =~ s/^s://;
+ my $force_ascii = to_bool($is_ascii && get_hex_key($real_key));
+ ($real_key, $mode eq 'restricted', $force_ascii);
+}
+
+sub convert_psk_key_for_wpa_supplicant {
+ my ($key) = @_;
+ my $l = length($key);
+ $l == 64 ?
+ get_hex_key($key) :
+ $l >= 8 && $l <= 63 ?
+ qq("$key") :
+ undef;
+}
+
+#- FIXME: to be improved (quotes, comments)
+sub wlan_ng_update_vars {
+ my ($file, $vars) = @_;
+ substInFile {
+ while (my ($key, $value) = each(%$vars)) {
+ s/^#?\Q$key\E=(?:"[^#]*"|[^#\s]*)(\s*#.*)?/$key=$value$1/ and delete $vars->{$key};
+ }
+ $_ .= join('', map { "$_=$vars->{$_}\n" } keys %$vars) if eof;
+ } $file;
+}
+
+sub wlan_ng_configure {
+ my ($essid, $key, $device, $module) = @_;
+ my $wlan_conf_file = "$::prefix/etc/wlan/wlan.conf";
+ my @wlan_devices = split(/ /, (cat_($wlan_conf_file) =~ /^WLAN_DEVICES="(.*)"/m)[0]);
+ push @wlan_devices, $device unless member($device, @wlan_devices);
+ #- enable device and make it use the choosen ESSID
+ wlan_ng_update_vars($wlan_conf_file,
+ {
+ WLAN_DEVICES => qq("@wlan_devices"),
+ "SSID_$device" => qq("$essid"),
+ "ENABLE_$device" => "y"
+ });
+
+ my $wlan_ssid_file = "$::prefix/etc/wlan/wlancfg-$essid";
+ #- copy default settings for this ESSID if config file does not exist
+ -f $wlan_ssid_file or cp_f("$::prefix/etc/wlan/wlancfg-DEFAULT", $wlan_ssid_file);
+
+ #- enable/disable encryption
+ wlan_ng_update_vars($wlan_ssid_file,
+ {
+ (map { $_ => $key ? "true" : "false" } qw(lnxreq_hostWEPEncrypt lnxreq_hostWEPDecrypt dot11PrivacyInvoked dot11ExcludeUnencrypted)),
+ AuthType => $key ? qq("sharedkey") : qq("opensystem"),
+ if_($key,
+ dot11WEPDefaultKeyID => 0,
+ dot11WEPDefaultKey0 => qq("$key")
+ )
+ });
+ #- hide settings for non-root users
+ chmod 0600, $wlan_conf_file;
+ chmod 0600, $wlan_ssid_file;
+
+ #- apply settings on wlan interface
+ require services;
+ services::restart($module eq 'prism2_cs' ? 'pcmcia' : 'wlan');
+}
+
+sub wpa_supplicant_get_driver {
+ my ($module) = @_;
+ $module =~ /^hostap_/ ? "hostap" :
+ $module eq "prism54" ? "prism54" :
+ $module =~ /^ath_/ ? "madwifi" :
+ $module =~ /^at76c50|atmel_/ ? "atmel" :
+ "wext";
+}
+
+sub wpa_supplicant_add_network {
+ my ($ui_input) = @_;
+ my $conf = wpa_supplicant_read_conf();
+
+ # use shorter variables
+ my $essid = $ui_input->{essid};
+ my $bssid = $ui_input->{bssid};
+ my $enc_mode = $ui_input->{encryption};
+ my $key = $ui_input->{key};
+ my $force_ascii = $ui_input->{force_ascii_key};
+ my $mode = $ui_input->{mode};
+
+ my $network = {
+ ssid => qq("$essid"),
+ scan_ssid => to_bool($bssid), #- hidden or non-broadcasted SSIDs
+ if_($bssid, bssid => $bssid),
+ if_($enc_mode ne 'none', priority => 1),
+ };
+
+ if ($enc_mode eq 'wpa-psk') {
+ $network->{psk} = convert_psk_key_for_wpa_supplicant($key);
+ } else {
+ $network->{key_mgmt} = 'NONE';
+ $network->{mode} = to_bool($mode eq 'Ad-hoc');
+ if (member($enc_mode, qw(open restricted))) {
+ put_in_hash($network, {
+ wep_key0 => convert_wep_key_for_wpa_supplicant($key, $force_ascii),
+ wep_tx_keyidx => 0,
+ auth_alg => $enc_mode eq 'restricted' ? 'SHARED' : 'OPEN',
+ });
+ }
+ }
+
+ #- handle extra variables as final overides
+ handle_extra_params($network, $ui_input->{extra});
+
+ @$conf = difference2($conf, [ wpa_supplicant_find_similar($conf, $network) ]);
+ push @$conf, $network;
+ wpa_supplicant_write_conf($conf);
+}
+
+sub wpa_supplicant_find_similar {
+ my ($conf, $network) = @_;
+ grep {
+ my $current = $_;
+ any { exists $network->{$_} && $network->{$_} eq $current->{$_} } qw(ssid bssid);
+ } @$conf;
+}
+
+sub wpa_supplicant_read_conf() {
+ my @conf;
+ my $network;
+ foreach (cat_($::prefix . $wpa_supplicant_conf)) {
+ if ($network) {
+ #- in a "network = {}" block
+ # value is either the string with "quotes" - or a full-length string
+ if (/^\s*(\w+)=\s*(?|([^"].*)|("[^"]*")).*$/) {
+ $network->{$1} = $2;
+ } elsif (/^\}/) {
+ #- end of network block
+ push @conf, $network;
+ undef $network;
+ }
+ } elsif (/^\s*network={/) {
+ #- beginning of a new network block
+ $network = {};
+ }
+ }
+ \@conf;
+}
+
+sub wpa_supplicant_write_conf {
+ my ($conf) = @_;
+ my $buf;
+ my @conf = @$conf;
+ my $network;
+ foreach (cat_($::prefix . $wpa_supplicant_conf)) {
+ if ($network) {
+ #- in a "network = {}" block
+ if (/^\s*(\w+)=(.*)$/) {
+ push @{$network->{entries}}, { key => $1, value => $2 };
+ member($1, qw(ssid bssid)) and $network->{$1} = $2;
+ } elsif (/^\}/) {
+ #- end of network block, write it
+ $buf .= "network={$network->{comment}\n";
+
+ my $new_network = first(wpa_supplicant_find_similar(\@conf, $network));
+ foreach (@{$network->{entries}}) {
+ my $key = $_->{key};
+ if ($new_network) {
+ #- do not write entry if not provided in the new network
+ exists $new_network->{$key} or next;
+ #- update value from the new network
+ $_->{value} = delete $new_network->{$key};
+ }
+ $buf .= " ";
+ $buf .= "$key=$_->{value}" if $key;
+ $buf .= "$_->{comment}\n";
+ }
+ if ($new_network) {
+ #- write new keys
+ while (my ($key, $value) = each(%$new_network)) {
+ $buf .= " $key=$value\n";
+ }
+ }
+ $buf .= "}\n";
+ $new_network and @conf = grep { $_ != $new_network } @conf;
+ undef $network;
+ } else {
+ #- unrecognized, keep it anyway
+ push @{$network->{entries}}, { comment => $_ };
+ }
+ } else {
+ if (/^\s*network={/) {
+ #- beginning of a new network block
+ $network = {};
+ } else {
+ #- keep other options, comments
+ $buf .= $_;
+ }
+ }
+ }
+
+ #- write remaining networks
+ foreach (@conf) {
+ $buf .= "\nnetwork={\n";
+ while (my ($key, $value) = each(%$_)) {
+ $buf .= " $key=$value\n";
+ }
+ $buf .= "}\n";
+ }
+
+ output($::prefix . $wpa_supplicant_conf, $buf);
+ #- hide keys for non-root users
+ chmod 0600, $::prefix . $wpa_supplicant_conf;
+}
+
+sub wpa_supplicant_load_eap_settings {
+ my ($network) = @_;
+ my $quoted_essid = qq("$network->{essid}");
+ my $conf = wpa_supplicant_read_conf();
+ foreach my $old_net (@$conf) {
+ if ($old_net->{ssid} eq $network->{essid} || $old_net->{ssid} eq $quoted_essid) {
+ $network->{extra} = '';
+ foreach my $eap_var (keys %eap_vars) {
+ next if $eap_var eq 'ssid';
+ my $ui_var = join('_', "eap", $eap_var);
+ if (defined $old_net->{$eap_var}) {
+ if ($eap_vars{$eap_var} == 0) {
+ if ($network->{extra} eq "") {
+ $network->{extra} = "$eap_var=$old_net->{$eap_var}";
+ } else {
+ $network->{extra} = join('#', $network->{extra}, "$eap_var=$old_net->{$eap_var}");
+ }
+ } else {
+ $network->{$ui_var} = $old_net->{$eap_var};
+ #- remove quotes on selected variables
+ $network->{$ui_var} = $1 if $eap_vars{$eap_var} == 2 && $network->{$ui_var} =~ /^"(.*)"$/;
+ if ($eap_var eq "proto") {
+ $network->{forceeap} = 'WPA2' if $old_net->{$eap_var} eq "RSN";
+ $network->{forceeap} = 'WPA' if $old_net->{$eap_var} eq "WPA";
+ }
+ }
+ }
+ }
+ last;
+ }
+ }
+}
+
+sub handle_extra_params {
+ my ($network, $extra) = @_;
+ #- handle extra variables as final overides
+ if (defined $extra && $extra ne "") {
+ #- FIXME: should split it on what the # sign?
+ foreach my $extra_var (split('#', $extra)) {
+ my ($key, $val) = split('=', $extra_var, 2);
+ $network->{$key} = $val;
+ }
+ }
+}
+sub wpa_supplicant_add_eap_network {
+ my ($ui_input) = @_;
+
+ #- expect all variables for us to be prefixed with eap_
+ my $conf = wpa_supplicant_read_conf();
+ my $default_eap_cfg = {
+ pairwise => 'CCMP TKIP',
+ group => 'CCMP TKIP',
+ proto => 'RSN WPA',
+ key_mgmt => 'WPA-EAP IEEE8021X NONE',
+ scan_ssid => 1,
+ };
+ if ($ui_input->{forceeap} eq 'WPA') {
+ #- WPA only
+ $default_eap_cfg->{pairwise} = 'TKIP';
+ $default_eap_cfg->{group} = 'TKIP';
+ $default_eap_cfg->{proto} = 'WPA';
+ } elsif ($ui_input->{forceeap} eq 'WPA2') {
+ #- WPA2 only
+ $default_eap_cfg->{pairwise} = 'CCMP TKIP';
+ $default_eap_cfg->{group} = 'CCMP TKIP';
+ $default_eap_cfg->{proto} = 'RSN';
+ }
+ my $network = { ssid => qq("$ui_input->{essid}") };
+ #- set the values
+ foreach my $eap_var (keys %eap_vars) {
+ my $key = join('_', "eap", $eap_var);
+ if (!defined $ui_input->{$key} || $ui_input->{$key} =~ /auto detect/i) {
+ $network->{$eap_var} = $default_eap_cfg->{$eap_var} if $default_eap_cfg->{$eap_var};
+ } else {
+ #- do not define if blank, the save routine will delete entry from file
+ next if !$ui_input->{$key};
+ $network->{$eap_var} = $eap_vars{$eap_var} == 2 ? qq("$ui_input->{$key}") : $ui_input->{$key};
+ }
+ }
+ #- handle extra variables as final overides
+ handle_extra_params($network, $ui_input->{extra});
+
+ $network->{mode} = to_bool($ui_input->{mode} eq 'Ad-hoc');
+
+ @$conf = difference2($conf, [ wpa_supplicant_find_similar($conf, $network) ]);
+ push @$conf, $network;
+ wpa_supplicant_write_conf($conf);
+}
+1;
diff --git a/lib/network/connection/xdsl.pm b/lib/network/connection/xdsl.pm
new file mode 100644
index 0000000..e55dd24
--- /dev/null
+++ b/lib/network/connection/xdsl.pm
@@ -0,0 +1,412 @@
+package network::connection::xdsl;
+
+use base qw(network::connection::ppp);
+
+use strict;
+use common;
+
+sub get_type_name() { N("DSL") }
+sub _get_type_icon() { 'xdsl' }
+
+sub get_devices() {
+ require detect_devices;
+ require network::connection::isdn;
+ require network::connection::ethernet;
+ my @usb_devices = detect_devices::get_xdsl_usb_devices();
+ $_->{xdsl_type} = 'usb' foreach @usb_devices;
+ my @capi_devices = grep { $_->{driver} =~ /dsl/i } map { network::connection::isdn::find_capi_card($_) } network::connection::isdn->get_devices;
+ $_->{xdsl_type} = 'capi' foreach @capi_devices;
+ my @ethernet_devices = network::connection::ethernet::get_devices();
+ $_->{xdsl_type} = 'ethernet' foreach @ethernet_devices;
+ @usb_devices, @capi_devices, @ethernet_devices;
+}
+
+sub get_metric { 25 }
+sub get_interface() { "ppp0" }
+
+sub get_up_timeout { 20 }
+
+my @non_ppp_protocols = qw(static dhcp);
+sub uses_ppp {
+ my ($self) = @_;
+ !member($self->{protocol}, @non_ppp_protocols);
+}
+
+sub uses_atm_arp {
+ my ($self) = @_;
+ $self->{device}{xdsl_type} eq 'usb' && !$self->uses_ppp;
+}
+sub get_atm_arp_interface { "atm0" }
+
+sub uses_atm_bridging {
+ my ($self) = @_;
+ $self->{device}{xdsl_type} eq 'usb' && member($self->{protocol}, qw(pppoe));
+}
+sub get_atm_bridging_interface { "nas0" }
+
+sub get_pppoe_interface {
+ my ($self) = @_;
+ $self->uses_atm_bridging
+ ? $self->get_atm_bridging_interface
+ : $self->network::connection::ethernet::get_interface;
+}
+
+my %protocol_settings = (
+ pppoa => {
+ plugin => sub {
+ my ($self) = @_;
+ "pppoatm.so " . join('.', $self->{access}{peer}{vpi}, $self->{access}{peer}{vci});
+ },
+ },
+ pppoe => {
+ pty => sub {
+ my ($self) = @_;
+ my $pppoe_interface = $self->get_pppoe_interface;
+ qq("pppoe -m 1412 -I $pppoe_interface");
+ },
+ options => [
+ qw(default-asyncmap noaccomp nobsdcomp novjccomp nodeflate),
+ "mru 1492",
+ "mtu 1492",
+ "lcp-echo-interval 20",
+ "lcp-echo-failure 3",
+ ],
+ },
+ pptp => {
+ pty => qq("/usr/sbin/pptp 10.0.0.138 --nolaunchpppd"),
+ options => [ qw(noipdefault) ],
+ },
+ capi => {
+ plugin => "capiplugin.so avmadsl",
+ options => [
+ qw(ipcp-accept-remote ipcp-accept-local sync noipx),
+ "connect /bin/true",
+ "lcp-echo-interval 5",
+ "lcp-echo-failure 3",
+ "lcp-max-configure 50",
+ "lcp-max-terminate 2",
+ "mru 1492",
+ "mtu 1492"
+ ],
+ },
+);
+
+my @thirdparty_settings = (
+ {
+ matching => 'speedtch',
+ description => N_("Alcatel speedtouch USB modem"),
+ url => "http://www.speedtouch.com/supuser.htm",
+ name => 'speedtouch',
+ firmware =>
+ {
+ package => 'speedtouch-firmware',
+ test_file => 'speedtch-*.bin*',
+ extract => {
+ name => 'speedtouch-firmware-extractor',
+ test_file => '/usr/sbin/firmware-extractor',
+ windows_source => 'alcaudsl.sys',
+ floppy_source => 'mgmt*.o',
+ default_source => '/usr/share/speedtouch/mgmt.o',
+ run => sub {
+ my ($file) = @_;
+ run_program::raw({ root => $::prefix, chdir => $network::thirdparty::firmware_directory },
+ '/usr/sbin/firmware-extractor', $file);
+ },
+ },
+ },
+ links => 'http://linux-usb.sourceforge.net/SpeedTouch/mandrake/index.html',
+ ppp => {
+ options => [ qw(noaccomp sync) ],
+ },
+ },
+
+ {
+ name => 'eciadsl',
+ explanations => N_("The ECI Hi-Focus modem cannot be supported due to binary driver distribution problem.
+
+You can find a driver on http://eciadsl.flashtux.org/"),
+ no_distro_package => 1,
+ tools => {
+ test_file => '/usr/sbin/pppoeci',
+ },
+ ppp => {
+ options => [
+ qw(noipdefault noaccomp sync),
+ "linkname eciadsl",
+ "lcp-echo-interval 0",
+ ],
+ protocols => {
+ pppoe => {
+ pty => sub {
+ my ($self) = @_;
+ qq("/usr/bin/pppoeci -v 1 -vpi $self->{access}{peer}{vpi} -vci $self->{access}{peer}{vci}");
+ },
+ },
+ },
+ },
+ },
+
+ {
+ matching => 'ueagle_atm',
+ description => 'Eagle chipset (from Analog Devices), e.g. Sagem F@st 800/840/908',
+ url => 'http://www.eagle-usb.org/',
+ name => 'ueagle',
+ firmware => {
+ test_file => 'ueagle-atm/eagle*.fw',
+ },
+ links => 'http://atm.eagle-usb.org/wakka.php?wiki=UeagleAtmDoc',
+ },
+
+ {
+ matching => qr/^unicorn_.*_atm$/,
+ description => 'Bewan Adsl (Unicorn)',
+ url => 'http://www.bewan.com/bewan/users/downloads/',
+ name => 'unicorn',
+ kernel_module => 1,
+ tools => {
+ optional => 1,
+ test_file => '/usr/bin/bewan_adsl_status',
+ },
+ sleep => 10,
+ ppp => {
+ options => [
+ qw(default-asyncmap hide-password noaccomp nobsdcomp nodeflate novjccomp sync),
+ "lcp-echo-interval 20",
+ "lcp-echo-failure 3",
+ ],
+ },
+ },
+
+ {
+ name => 'cxacru',
+ firmware => {
+ test_file => 'cxacru-fw.bin',
+ no_distro_package => 1,
+ explanations => N_("Modems using Conexant AccessRunner chipsets cannot be supported due to binary firmware distribution problem."),
+ url => 'http://accessrunner.sourceforge.net/firmware.shtml',
+ },
+ }
+);
+
+sub get_thirdparty_settings() {
+ \@thirdparty_settings;
+}
+
+sub get_providers {
+ my ($self) = @_;
+ require network::connection::providers::xdsl;
+ if_($self->{device}{xdsl_type} ne 'capi', \%network::connection::providers::xdsl::data, '|');
+}
+
+sub get_protocols {
+ my ($self) = @_;
+ $self->{device}{xdsl_type} eq 'capi' ?
+ {
+ capi => N("DSL over CAPI"),
+ } :
+ {
+ dhcp => N("Dynamic Host Configuration Protocol (DHCP)"),
+ static => N("Manual TCP/IP configuration"),
+ pptp => N("Point to Point Tunneling Protocol (PPTP)"),
+ pppoe => N("PPP over Ethernet (PPPoE)"),
+ pppoa => N("PPP over ATM (PPPoA)"),
+ };
+}
+
+sub guess_protocol {
+ my ($self, $net) = @_;
+ $self->{protocol} = $self->{provider} && $self->{provider}{method};
+ if ($self->{device}{xdsl_type} eq 'capi') {
+ $self->{protocol} = 'capi';
+ } elsif ($self->{device}{xdsl_type} eq 'ethernet') {
+ require network::connection::ethernet;
+ my $interface = $self->network::connection::ethernet::get_interface;
+ if (my $ifcfg = $net->{ifcfg}{$interface}) {
+ $self->{protocol} = $ifcfg->{BOOTPROTO} if member($ifcfg->{BOOTPROTO}, @non_ppp_protocols);
+ $self->{protocol} ||= 'dhcp';
+ #- pppoa shouldn't be selected by default for ethernet devices, fallback on pppoe
+ $self->{protocol} = 'pppoe' if $self->{protocol} eq 'pppoa';
+ }
+ }
+}
+
+sub guess_access_settings {
+ my ($self) = @_;
+ require network::adsl;
+ my $probe = {};
+ network::adsl::adsl_probe_info($probe);
+ $self->{access}{login} = $probe->{adsl}{login};
+ $self->{access}{password} = $probe->{adsl}{passwd};
+ $self->{access}{peer}{$_} = $probe->{adsl}{$_} foreach qw(vpi vci);
+ if ($self->{provider}) {
+ $self->{access}{peer}{$_} = hex($self->{provider}{$_}) foreach qw(vpi vci);
+ }
+}
+
+sub get_access_settings {
+ my ($self) = @_;
+
+ [
+ @{$self->network::connection::ppp::get_access_settings},
+ if_(member($self->{protocol}, qw(pppoa pppoe)),
+ { label => N("Virtual Path ID (VPI):"), val => \$self->{access}{peer}{vpi}, advanced => 1 },
+ { label => N("Virtual Circuit ID (VCI):"), val => \$self->{access}{peer}{vci}, advanced => 1 }
+ ),
+ ];
+}
+
+sub get_peer_default_options {
+ my ($self) = @_;
+ $self->network::connection::ppp::get_peer_default_options,
+ qw(lock persist nopcomp noccp novj),
+ "kdebug 1",
+ "holdoff 4",
+ "maxfail 5";
+}
+
+sub build_peer {
+ my ($self) = @_;
+ my $may_call = sub { ref $_[0] eq 'CODE' ? $_[0]->($self) : $_[0] };
+ my @ppp_fields = qw(plugin pty);
+ my @ppp_options;
+ if ($self->{thirdparty}) {
+ foreach my $settings (grep { $_ } $self->{thirdparty}{ppp}{protocols}{$self->{protocol}}, $self->{thirdparty}{ppp}) {
+ @ppp_options = @{$settings->{options}} if $settings->{options};
+ foreach (@ppp_fields) {
+ $self->{access}{peer}{$_} ||= $may_call->($settings->{$_}) if defined $settings->{$_};
+ }
+ }
+ }
+ if (my $generic_settings = $protocol_settings{$self->{protocol}}) {
+ @ppp_options = @{$generic_settings->{options} || []} if !@ppp_options;
+ foreach (@ppp_fields) {
+ $self->{access}{peer}{$_} ||= $may_call->($generic_settings->{$_}) if defined $generic_settings->{$_};
+ }
+ }
+
+ @ppp_options, #- write them before pty/plugin stuff
+ $self->network::connection::ppp::build_peer;
+}
+
+sub write_settings {
+ my ($self, $net) = @_;
+
+ if ($self->{device}{xdsl_type} eq 'ethernet' && $self->{protocol} eq 'pppoe') {
+ my $interface = $self->network::connection::ethernet::get_interface;
+ $net->{ifcfg}{$interface} = {
+ DEVICE => $interface,
+ BOOTPROTO => 'none',
+ NETMASK => '255.255.255.0',
+ NETWORK => '10.0.0.0',
+ BROADCAST => '10.0.0.255',
+ MII_NOT_SUPPORTED => 'yes',
+ ONBOOT => 'yes',
+ };
+ }
+
+ if ($self->{protocol} eq 'capi') {
+ require network::connection::isdn;
+ network::connection::isdn::write_capi_conf($self->{device});
+ }
+
+ #- TODO: add "options ueagle-atm cmv_file= $net->{adsl}{cmv}.bin" in /etc/modprobe.d/ueagle-atm
+ # if ($self->get_driver eq 'ueagle-atm') { ... }
+
+ if ($self->uses_ppp) {
+ $self->network::connection::ppp::write_settings;
+ } else {
+ $self->network::connection::write_settings;
+ }
+}
+
+sub build_ifcfg_settings {
+ my ($self) = @_;
+ my $settings = {
+ if_($self->uses_ppp, TYPE => 'ADSL'),
+ };
+ if ($self->uses_atm_arp) {
+ #- use ATMARP with the atm0 interface
+ put_in_hash($settings, {
+ DEVICE => $self->get_atm_arp_interface,
+ ATM_ADDR => join('.', @{$self->{access}{peer}}{qw(vpi vci)}),
+ MII_NOT_SUPPORTED => "yes",
+ });
+ }
+ if ($self->uses_atm_bridging) {
+ put_in_hash($settings, {
+ ATM_DEVICE => $self->get_atm_bridging_interface,
+ ATM_ADDR => join('.', @{$self->{access}{peer}}{qw(vpi vci)}),
+ });
+ }
+ $self->network::connection::build_ifcfg_settings($settings);
+}
+
+sub unload_connection {
+ my ($self) = @_;
+ require network::connection::isdn;
+ network::connection::isdn::unload_connection($self->{device}) if $self->{protocol} eq 'capi';
+}
+
+sub install_packages {
+ my ($self, $in) = @_;
+ my $per_type_packages = {
+ pppoa => [ qw(ppp-pppoatm) ],
+ pppoe => [ qw(rp-pppoe) ],
+ pptp => [ qw(pptp-linux) ],
+ capi => [ qw(ppp) ],
+ };
+ my @packages = @{$per_type_packages->{$self->{protocol}} || []};
+ push @packages, 'linux-atm' if $self->uses_atm_arp || $self->uses_atm_bridging;
+ if (@packages && !$in->do_pkgs->install(@packages)) {
+ $in->ask_warn(N("Error"), N("Could not install the packages (%s)!", @packages));
+ return;
+ }
+ if ($self->{protocol} eq 'capi') {
+ require network::connection::isdn;
+ network::connection::isdn::install_packages($self->{device}, $in);
+ $in->do_pkgs->ensure_is_installed_if_available("drdsl", "/usr/sbin/drdsl");
+ }
+ 1;
+}
+
+sub prepare_connection {
+ my ($self) = @_;
+
+ if ($::isInstall) {
+ #- load modules that are not automatically loaded during install
+ my @modules = qw(ppp_synctty ppp_async ppp_generic n_hdlc); #- required for pppoe/pptp connections
+ push @modules, 'pppoatm' if $self->{protocol} eq 'pppoa';
+ foreach (@modules) {
+ eval { modules::load($_) } or log::l("failed to load $_ module: $@");
+ }
+ }
+
+ if ($self->{protocol} eq 'capi') {
+ require network::connection::isdn;
+ network::connection::isdn::prepare_connection($self->{device});
+ require run_program;
+ run_program::rooted($::prefix, "/usr/sbin/drdsl");
+ }
+
+ 1;
+}
+
+sub connect {
+ my ($self) = @_;
+ if ($self->{device}{xdsl_type} eq 'ethernet') {
+ require network::tools;
+ network::tools::start_interface($self->network::connection::ethernet::get_interface, 0);
+ }
+ $self->network::connection::connect;
+}
+
+sub disconnect {
+ my ($self) = @_;
+ $self->network::connection::disconnect;
+ if ($self->{device}{xdsl_type} eq 'ethernet') {
+ require network::tools;
+ network::tools::stop_interface($self->network::connection::ethernet::get_interface, 0);
+ }
+}
+
+1;
diff --git a/lib/network/connection_manager.pm b/lib/network/connection_manager.pm
new file mode 100644
index 0000000..e6b2a83
--- /dev/null
+++ b/lib/network/connection_manager.pm
@@ -0,0 +1,506 @@
+package network::connection_manager;
+
+use strict;
+
+use common;
+use run_program;
+use detect_devices;
+use interactive;
+use mygtk2;
+use ugtk2 qw(:create :helpers :wrappers);
+use Gtk2::SimpleList;
+use network::signal_strength;
+use network::network;
+use network::tools;
+use network::connection;
+use modules;
+use locale; # for cmp
+
+sub create_pixbufs() {
+ {
+ state => { map { $_ => gtkcreate_pixbuf($_) } qw(connected disconnected refresh) },
+ link_level => { map {
+ $_ => gtkcreate_pixbuf('wifi-' . sprintf('%03d', $_))->scale_simple(24, 24, 'hyper');
+ } qw(20 40 60 80 100) },
+ encryption => { map {
+ $_ => gtkcreate_pixbuf("encryption-$_-24");
+ } qw(open weak strong) },
+ };
+}
+
+sub new {
+ my ($class, $in, $net, $w, $pixbufs) = @_;
+ bless {
+ in => $in, net => $net, gui => { w => $w, pixbufs => $pixbufs },
+ }, $class;
+}
+
+sub set_connection {
+ my ($cmanager, $connection) = @_;
+ $cmanager->{connection} = $connection;
+ $cmanager->{wait_message_timeout} = 20*1000 if ref($connection) eq 'network::connection::wireless';
+}
+
+sub check_setup {
+ my ($cmanager) = @_;
+ $cmanager->{connection}{passed_setup} =
+ (!$cmanager->{connection}->can("check_device") ||
+ $cmanager->{connection}->check_device) &&
+ (!$cmanager->{connection}->can("check_hardware") ||
+ !$cmanager->{connection}->check_hardware_is_slow && $cmanager->{connection}->check_hardware)
+ if !defined $cmanager->{connection}{passed_setup};
+ $cmanager->{connection}{passed_setup};
+}
+
+sub setup_connection {
+ my ($cmanager) = @_;
+
+ $cmanager->load_settings;
+
+ my @packages = $cmanager->{connection}->can('get_packages') ? $cmanager->{connection}->get_packages : ();
+ if (@packages && !$cmanager->{in}->do_pkgs->install(@packages)) {
+ $cmanager->{in}->ask_warn(N("Error"), N("Could not install the packages (%s)!", join(', ', @packages)));
+ return;
+ }
+ $cmanager->{connection}->prepare_device;
+ $cmanager->{connection}->setup_thirdparty($cmanager->{in}) or return;
+ if ($cmanager->{connection}->can("check_device") && !$cmanager->{connection}->check_device) {
+ $cmanager->{in}->ask_warn(N("Error"), $cmanager->{connection}{device}{error});
+ return;
+ }
+ my $device_ready = 1;
+ if ($cmanager->{connection}->can('check_hardware')) {
+ #- FIXME: change message to "Checking device..." in cooker
+ my $_wait = $cmanager->{in}->wait_message(N("Please wait"), N("Configuring device..."));
+ $device_ready = $cmanager->{connection}->check_hardware;
+ }
+ if ($cmanager->{connection}->can('get_hardware_settings') && !$device_ready) {
+ $cmanager->{in}->ask_from_({
+ title => N("Network settings"),
+ messages => N("Please enter settings for network"),
+ auto_window_size => 1,
+ }, $cmanager->{connection}->get_hardware_settings) or return;
+ if ($cmanager->{connection}->can("check_hardware_settings") && !$cmanager->{connection}->check_hardware_settings) {
+ $cmanager->{in}->ask_warn(N("Error"), $cmanager->{connection}->{hardware}{error});
+ return;
+ }
+ }
+ if ($cmanager->{connection}->can('configure_hardware') && !$device_ready) {
+ my $wait = $cmanager->{in}->wait_message(N("Please wait"), N("Configuring device..."));
+ if (!$cmanager->{connection}->configure_hardware) {
+ undef $wait;
+ $cmanager->{in}->ask_warn(N("Error"), $cmanager->{connection}{hardware}{error}) if $cmanager->{connection}{hardware}{error};
+ return;
+ }
+ }
+ $cmanager->write_settings;
+ $cmanager->{connection}{passed_setup} = 1;
+}
+
+sub load_settings {
+ my ($cmanager) = @_;
+
+ $cmanager->{connection}->load_interface_settings;
+ $cmanager->{connection}->guess_hardware_settings if $cmanager->{connection}->can('guess_hardware_settings');
+ $cmanager->{connection}->guess_network_access_settings if $cmanager->{connection}->can('guess_network_access_settings');
+ if ($cmanager->{connection}->can('get_providers')) {
+ $cmanager->{connection}->guess_provider_settings;
+ $cmanager->{connection}->set_provider;
+ }
+ $cmanager->{connection}->guess_protocol($cmanager->{net}) if $cmanager->{connection}->can('guess_protocol');
+ $cmanager->{connection}->guess_access_settings if $cmanager->{connection}->can('guess_access_settings');
+ $cmanager->{connection}->guess_address_settings if $cmanager->{connection}->can('guess_address_settings');
+ $cmanager->{connection}->guess_hostname_settings if $cmanager->{connection}->can('guess_hostname_settings');
+ $cmanager->{connection}->guess_network_control_settings if $cmanager->{connection}->can('guess_network_control_settings');
+ $cmanager->{connection}->guess_control_settings;
+}
+
+sub write_settings {
+ my ($cmanager) = @_;
+
+ my $modules_conf = modules::any_conf->read;
+ $cmanager->{connection}->write_settings($cmanager->{net}, $modules_conf);
+ $modules_conf->write;
+}
+
+sub configure_connection {
+ my ($cmanager) = @_;
+
+ if (!$cmanager->check_setup) {
+ $cmanager->setup_connection or return;
+ $cmanager->update_networks if $cmanager->{connection}->can('get_networks');
+ $cmanager->update_on_status_change;
+ return;
+ }
+
+ $cmanager->load_settings;
+ my $system_file = '/etc/sysconfig/drakx-net';
+ my %global_settings = getVarsFromSh($system_file);
+
+ my $error;
+ do {
+ undef $error;
+ $cmanager->{in}->ask_from_({
+ title => N("Network settings"),
+ messages => N("Please enter settings for network"),
+ icon => $cmanager->{connection}->get_type_icon(48),
+ banner_title => $cmanager->{connection}->get_description,
+ },
+ [
+ $cmanager->{connection}->can('get_network_access_settings') ? (
+ { label => $cmanager->{connection}->get_network_access_settings_label, title => 1, advanced => 1 },
+ @{$cmanager->{connection}->get_network_access_settings},
+ ) : (),
+ $cmanager->{connection}->can('get_providers') ? (
+ @{$cmanager->{connection}->get_provider_settings($cmanager->{net})}
+ ) : (),
+ $cmanager->{connection}->can('get_protocols') ? (
+ @{$cmanager->{connection}->get_protocol_settings},
+ ) : (),
+ $cmanager->{connection}->can('get_access_settings') ? (
+ { label => $cmanager->{connection}->get_access_settings_label, title => 1, advanced => 1 },
+ @{$cmanager->{connection}->get_access_settings}
+ ) : (),
+ $cmanager->{connection}->can('get_address_settings') && !text2bool($global_settings{AUTOMATIC_ADDRESS}) ? (
+ { label => $cmanager->{connection}->get_address_settings_label, title => 1, advanced => 1 },
+ @{$cmanager->{connection}->get_address_settings('show_all')}
+ ) : (),
+ $cmanager->{connection}->can('get_network_control_settings') ? (
+ @{$cmanager->{connection}->get_network_control_settings}
+ ) : (),
+ $cmanager->{connection}->can('get_control_settings') ? (
+ @{$cmanager->{connection}->get_control_settings}
+ ) : (),
+ ],
+ ) or return;
+ if ($cmanager->{connection}->can('check_network_access_settings') && !$cmanager->{connection}->check_network_access_settings) {
+ $cmanager->{in}->ask_warn(N("Error"), $cmanager->{connection}{network_access}{error}{message});
+ $error = 1;
+ }
+ if ($cmanager->{connection}->can('check_address_settings') && !$cmanager->{connection}->check_address_settings($cmanager->{net})) {
+ $cmanager->{in}->ask_warn(N("Error"), $cmanager->{connection}{address}{error}{message});
+ $error = 1;
+ }
+ } while $error;
+
+ $cmanager->{connection}->install_packages($cmanager->{in}) if $cmanager->{connection}->can('install_packages');
+ $cmanager->{connection}->unload_connection if $cmanager->{connection}->can('unload_connection');
+
+ $cmanager->write_settings;
+
+ 1;
+}
+
+sub start_connection {
+ my ($cmanager) = @_;
+
+ $cmanager->{connection} or return;
+ if ($cmanager->{connection}->can('get_networks')) {
+ $cmanager->{connection}{network} &&
+ ($cmanager->{connection}->selected_network_is_configured ||
+ $cmanager->configure_connection)
+ or return;
+ }
+
+ gtkset_mousecursor_wait($cmanager->{gui}{w}{window}->window);
+ my $wait = $cmanager->{in}->wait_message(N("Please wait"), N("Connecting..."));
+ if ($cmanager->{connection}->can('apply_network_selection')) {
+ $cmanager->load_settings;
+ $cmanager->{connection}->apply_network_selection($cmanager);
+ }
+ $cmanager->{connection}->prepare_connection if $cmanager->{connection}->can('prepare_connection');
+ $cmanager->{connection}->disconnect;
+ $cmanager->{connection}->connect($cmanager->{in}, $cmanager->{net});
+ gtkset_mousecursor_normal($cmanager->{gui}{w}{window}->window);
+
+ $cmanager->update_on_status_change;
+ if ($cmanager->{wait_message_timeout}) {
+ $cmanager->{wait_message} = $wait;
+ Glib::Timeout->add($cmanager->{wait_message_timeout},
+ sub {
+ if ($cmanager->{wait_message}) {
+ undef $cmanager->{wait_message};
+ $cmanager->{in}->ask_warn(N("Error"), N("Connection failed."))
+ if !$cmanager->{connection}->get_status;
+ }
+ undef;
+ });
+ };
+}
+
+sub stop_connection {
+ my ($cmanager) = @_;
+
+ gtkset_mousecursor_wait($cmanager->{gui}{w}{window}->window);
+ my $_wait = $cmanager->{in}->wait_message(N("Please wait"), N("Disconnecting..."));
+ $cmanager->{connection}->disconnect;
+ gtkset_mousecursor_normal($cmanager->{gui}{w}{window}->window);
+
+ $cmanager->update_on_status_change;
+}
+
+sub monitor_connection {
+ my ($cmanager) = @_;
+ my $interface = $cmanager->{connection} && $cmanager->{connection}->get_interface or return;
+ run_program::raw({ detach => 1 }, '/usr/bin/net_monitor', '--defaultintf', $interface);
+}
+
+sub toggle_would_disconnect {
+ my ($cmanager) = @_;
+
+ my $network = $cmanager->{connection} && $cmanager->{connection}->get_selected_network;
+ $cmanager->{connection} && $cmanager->{connection}->get_status &&
+ (!$network || keys(%{$cmanager->{connection}{networks}}) <= 1 || $network->{current});
+}
+
+sub toggle_connection {
+ my ($cmanager) = @_;
+
+ if ($cmanager->toggle_would_disconnect) {
+ $cmanager->stop_connection;
+ } else {
+ $cmanager->start_connection;
+ }
+}
+
+sub create_networks_list {
+ my ($cmanager) = @_;
+
+ if ($cmanager->{gui}{show_unique_network}) {
+ $cmanager->{gui}{networks_list} = gtknew('HBox', spacing => 20);
+ return;
+ }
+
+ $cmanager->{gui}{networks_list} = Gtk2::SimpleList->new(
+ "AP" => "hidden",
+ '' => "pixbuf",
+ N("SSID") => "text",
+ N("Signal strength") => "pixbuf",
+ N("Encryption") => "pixbuf",
+ N("Operating Mode") => "text",
+ );
+ $cmanager->{gui}{networks_list}->get_selection->set_mode('single');
+ $cmanager->{gui}{networks_list}->get_selection->signal_connect('changed' => sub { $cmanager->select_network });
+
+ $cmanager->{gui}{networks_list}->signal_connect('query-tooltip' => sub {
+ my ($widget, $x, $y, $kbd_tip, $tooltip) = @_;
+ (undef, undef, my $model, my $path, my $iter) = $widget->get_tooltip_context($x, $y, $kbd_tip) or return;
+ my $ap = $model->get($iter, 0);
+ my $network = $cmanager->{connection}{networks}{$ap};
+ $tooltip->set_text(sprintf("%2.2f%% %s\n", $network->{signal_strength}, $network->{flags}));
+ $widget->set_tooltip_row($tooltip, $path);
+ 1;
+ });
+ $cmanager->{gui}{networks_list}->set_has_tooltip(1);
+ $cmanager->{gui}{networks_list}->get_column(1)->set_sort_column_id(1);
+ $cmanager->{gui}{networks_list}->get_model->set_sort_func (1, sub {
+ my ($sortable, $iter_left, $iter_right) = @_;
+ my $s1 = $sortable->get($iter_left, 2);
+ my $s2 = $sortable->get($iter_right, 2);
+ return $s1 cmp $s2;
+ });
+ $cmanager->{gui}{networks_list}->get_column(2)->set_sort_column_id(2);
+ $cmanager->{gui}{networks_list}->get_model->set_sort_func (2, sub {
+ my ($sortable, $iter_left, $iter_right) = @_;
+ my $s1 = $cmanager->{connection}{networks}{$sortable->get($iter_left, 0)}->{signal_strength};
+ my $s2 = $cmanager->{connection}{networks}{$sortable->get($iter_right, 0)}->{signal_strength};
+ return $s1 <=> $s2;
+ });
+ $cmanager->{gui}{networks_list}->get_column(3)->set_sort_column_id(3);
+ $cmanager->{gui}{networks_list}->get_model->set_sort_func (3, sub {
+ my ($sortable, $iter_left, $iter_right) = @_;
+ my $s1 = $cmanager->{connection}{networks}{$sortable->get($iter_left, 0)}->{flags};
+ my $s2 = $cmanager->{connection}{networks}{$sortable->get($iter_right, 0)}->{flags};
+ #FIXME Should define an explicit order OPEN < WEP < WPA
+ return $s1 cmp $s2;
+ });
+ $cmanager->{gui}{networks_list}->set_enable_search(1);
+ $cmanager->{gui}{networks_list}->set_search_column(1);
+ $cmanager->{gui}{networks_list}->set_search_equal_func(sub {
+ my ($model, $column, $key, $iter, $data) = @_;
+ return $model->get($iter, 2) !~ /^\Q$key/i;
+ });
+ # Sort by signal level by default
+ $cmanager->{gui}{networks_list}->get_model->set_sort_column_id(2, 'descending');
+}
+
+sub select_network {
+ my ($cmanager) = @_;
+
+ if ($cmanager->{connection}) {
+ my ($selected) = $cmanager->{gui}{networks_list}->get_selected_indices;
+ $cmanager->{connection}{network} = defined $selected && $cmanager->{gui}{networks_list}{data}[$selected][0];
+ }
+ $cmanager->update_on_status_change;
+}
+
+sub filter_networks {
+ my ($connection) = @_;
+ $_->{configured} = $connection->network_is_configured($_) foreach values %{$connection->{networks}};
+ sort {
+ $b->{current} <=> $a->{current} || $b->{configured} <=> $a->{configured} || $b->{signal_strength} <=> $a->{signal_strength} || $a->{name} cmp $b->{name};
+ } values %{$connection->{networks}};
+}
+
+sub update_networks {
+ my ($cmanager) = @_;
+
+ @{$cmanager->{gui}{networks_list}{data}} = ();
+
+ if ($cmanager->{connection}) {
+ $cmanager->check_setup || $cmanager->setup_connection or return;
+
+ my $wait = $cmanager->{connection}->network_scan_is_slow && $cmanager->{in}->wait_message(N("Please wait"), N("Scanning for networks..."));
+ $cmanager->{connection}{networks} = $cmanager->{connection}->get_networks($cmanager->{net});
+ $cmanager->{connection}{network} ||= find { $cmanager->{connection}{networks}{$_}{current} } keys %{$cmanager->{connection}{networks}};
+
+ my $routes = network::tools::get_routes();
+ my $interface = $cmanager->{connection}->get_interface;
+ my $connected = exists $routes->{$interface}{network};
+
+ my @networks = filter_networks($cmanager->{connection});
+ foreach my $network (@networks) {
+ my $ap = $network->{ap};
+ my $connected_pixbuf = $network->{current} ? $connected ? $cmanager->{gui}{pixbufs}{state}{connected} : $cmanager->{gui}{pixbufs}{state}{refresh} : undef;
+ my $network_name = !$network->{essid} && exists $cmanager->{net}{wireless}{$ap} && $cmanager->{net}{wireless}{$ap}{WIRELESS_ESSID} || $network->{name};
+ my $strength_pixbuf = network::signal_strength::get_strength_icon($network);
+
+ if ($cmanager->{gui}{show_unique_network}) {
+ gtkset($cmanager->{gui}{networks_list}, children => [
+ 1, $network_name,
+ 0, Gtk2::Image->new_from_pixbuf($strength_pixbuf),
+ ]);
+ $cmanager->{connection}{network} = $network_name;
+ } else {
+ push @{$cmanager->{gui}{networks_list}{data}}, [
+ $ap || $network->{name},
+ $connected_pixbuf,
+ $network_name,
+ $strength_pixbuf,
+ $cmanager->{gui}{pixbufs}{encryption}{$network->{flags} =~ /WPA/i ? 'strong' : $network->{flags} =~ /WEP/i ? 'weak' : 'open'},
+ $network->{mode},
+ ];
+ }
+ }
+
+ if ($cmanager->{connection}{network} && !$cmanager->{gui}{show_unique_network}) {
+ my $index = eval { find_index { $_->[0] eq $cmanager->{connection}{network} } @{$cmanager->{gui}{networks_list}{data}} };
+ $cmanager->{gui}{networks_list}->select($index) if defined $index;
+ }
+
+ undef $wait;
+ }
+
+ $cmanager->update_on_status_change;
+}
+
+sub update_on_status_change {
+ my ($cmanager) = @_;
+
+ if ($cmanager->{gui}{buttons}{connect_toggle}) {
+ my $disconnect = $cmanager->toggle_would_disconnect;
+ $cmanager->{gui}{buttons}{connect_toggle}->set_label($disconnect ? N("Disconnect") : N("Connect"));
+ gtkset($cmanager->{gui}{buttons}{connect_toggle}, image => gtknew('Image', file => $disconnect ? 'stop-16' : 'activate-16'))
+ if $cmanager->{gui}{buttons}{connect_toggle}->get_image;
+ $cmanager->{gui}{buttons}{connect_toggle}->set_sensitive(
+ $cmanager->{connection} && (
+ !$cmanager->{connection}->can('get_networks') ||
+ $cmanager->{connection}->get_status || #- always allow to disconnect if connected
+ $cmanager->{connection}{network}
+ ));
+ }
+
+ $cmanager->{gui}{buttons}{connect_start}->set_sensitive($cmanager->{connection} && (!$cmanager->{connection}->get_status || $cmanager->{connection}{network}))
+ if $cmanager->{gui}{buttons}{connect_start};
+ $cmanager->{gui}{buttons}{connect_stop}->set_sensitive($cmanager->{connection} && $cmanager->{connection}->get_status)
+ if $cmanager->{gui}{buttons}{connect_stop};
+
+ my $allow_configure;
+ if ($cmanager->{connection}) {
+ my $may_have_network =
+ !$cmanager->{connection}->can('get_networks') ||
+ $cmanager->{connection}{network};
+ $allow_configure = $may_have_network || !$cmanager->check_setup;
+ }
+
+ $cmanager->{gui}{buttons}{configure}->set_sensitive($allow_configure)
+ if $cmanager->{gui}{buttons}{configure};
+
+ my $has_interface = to_bool($cmanager->{connection} && $cmanager->{connection}->get_interface);
+ $cmanager->{gui}{buttons}{refresh}->set_sensitive($has_interface)
+ if $cmanager->{gui}{buttons}{refresh};
+ $cmanager->{gui}{buttons}{monitor}->set_sensitive($has_interface)
+ if $cmanager->{gui}{buttons}{monitor};
+
+ if ($cmanager->{gui}{status_image} && $cmanager->{connection}) {
+ my $icon = $cmanager->{connection}->get_status_icon;
+ ugtk2::_find_imgfile($icon) or $icon = $cmanager->{connection}->get_type_icon;
+ gtkset($cmanager->{gui}{status_image}, file => $icon);
+ }
+}
+
+sub _get_network_event_message {
+ my ($connections, $member, @args) = @_;
+ #- FIXME: the hostname.d script and s2u use a different D-Bus interface
+ if ($member eq 'hostname') {
+ my ($hostname) = @args;
+ N("Hostname changed to \"%s\"", $hostname);
+ } elsif ($member eq 'status') {
+ my ($status, $interface) = @args;
+ my $event_connection = find { $_->get_interface eq $interface } @$connections;
+ $event_connection && $event_connection->get_status_message($status);
+ }
+}
+
+sub setup_dbus_handlers {
+ my ($cmanagers, $connections, $on_network_event, $dbus) = @_;
+ #- FIXME: use network::monitor?
+ $dbus->{connection}->add_filter(
+ sub {
+ my ($_con, $msg) = @_;
+ if ($msg->get_interface eq 'com.mandriva.network') {
+ my $member = $msg->get_member;
+ my $message = _get_network_event_message($connections, $member, $msg->get_args_list);
+ $on_network_event->($message) if $on_network_event && $message;
+ if ($member eq 'status') {
+ my ($status, $interface) = $msg->get_args_list;
+ print "got connection status event: $status $interface\n";
+ my $cmanager = find { $_->{connection}->get_interface eq $interface } @$cmanagers
+ or return;
+ #- FIXME: factorize in update_on_status_change() and check why update_networks() calls update_on_status_change()
+ if ($cmanager->{connection}->can('get_networks') && !$cmanager->{connection}->network_scan_is_slow) {
+ $cmanager->update_networks;
+ } else {
+ $cmanager->network::connection_manager::update_on_status_change;
+ }
+ if ($cmanager->{wait_message}) {
+ if ($status eq 'interface_up') {
+ undef $cmanager->{wait_message};
+ } elsif ($status =~ /_failure$/) {
+ undef $cmanager->{wait_message};
+ $cmanager->{in}->ask_warn(N("Error"), join("\n", N("Connection failed."), if_($message, $message)));
+ }
+ }
+ }
+ }
+ if ($msg->get_interface eq 'com.mandriva.monitoring.wireless' && $msg->get_member eq 'Event') {
+ my ($event, $interface) = $msg->get_args_list;
+ print "got wireless event: $event $interface\n";
+ # eugeni: wpa_supplicant seems to issue 'Authentication..timed out messages' even if they
+ # are not fatal (#54002). We should either handle them with more care, or just ignore them altogether
+# my $cmanager = find { $_->{connection}->get_interface eq $interface } @$cmanagers;
+# if ($cmanager && $cmanager->{wait_message}) {
+# # CTRL-EVENT-CONNECTED does not have to be handled, further status will be handled by interface status code
+# if ($event =~ /Authentication with (.+?) timed out/) {
+# undef $cmanager->{wait_message};
+# $cmanager->{in}->ask_warn(N("Error"), N("Connection failed."));
+# }
+# }
+ }
+ });
+ $dbus->{connection}->add_match("type='signal',interface='com.mandriva.network'");
+ $dbus->{connection}->add_match("type='signal',interface='com.mandriva.monitoring.wireless'");
+ dbus_object::set_gtk2_watch_helper($dbus);
+}
+
+1;
diff --git a/lib/network/dhcpd.pm b/lib/network/dhcpd.pm
new file mode 100644
index 0000000..8cf30d5
--- /dev/null
+++ b/lib/network/dhcpd.pm
@@ -0,0 +1,50 @@
+package network::dhcpd;
+
+use strict;
+use common;
+
+my $sysconf_dhcpd = "$::prefix/etc/sysconfig/dhcpd";
+my $dhcpd_conf_file = "$::prefix/etc/dhcpd.conf";
+my $update_dhcp = "/usr/sbin/update_dhcp.pl";
+
+sub read_dhcpd_conf {
+ my ($o_file) = @_;
+ my $s = cat_($o_file || $dhcpd_conf_file);
+ { option_routers => [ $s =~ /^\s*option routers\s+(\S+);/mg ],
+ subnet_mask => [ if_($s =~ /^\s*option subnet-mask\s+(.*);/mg, split(' ', $1)) ],
+ domain_name => [ if_($s =~ /^\s*option domain-name\s+"(.*)";/mg, split(' ', $1)) ],
+ domain_name_servers => [ if_($s =~ /^\s*option domain-name-servers\s+(.*);/m, split(' ', $1)) ],
+ dynamic_bootp => [ if_($s =~ /^\s*range dynamic-bootp\s+\S+\.(\d+)\s+\S+\.(\d+)\s*;/m, split(' ', $1)) ],
+ default_lease_time => [ if_($s =~ /^\s*default-lease-time\s+(.*);/m, split(' ', $1)) ],
+ max_lease_time => [ if_($s =~ /^\s*max-lease-time\s+(.*);/m, split(' ', $1)) ] };
+}
+
+sub write_dhcpd_conf {
+ my ($dhcpd_conf, $device) = @_;
+
+ my ($lan) = $dhcpd_conf->{option_routers}[0] =~ /^(.*)\.\d+$/;
+ log::explanations("Configuring a DHCP server on $lan.0");
+
+ renamef($dhcpd_conf_file, "$dhcpd_conf_file.old");
+ output($dhcpd_conf_file, qq(subnet $lan.0 netmask $dhcpd_conf->{subnet_mask}[0] {
+ # default gateway
+ option routers $dhcpd_conf->{option_routers}[0];
+ option subnet-mask $dhcpd_conf->{subnet_mask}[0];
+
+ option domain-name "$dhcpd_conf->{domain_name}[0]";
+ option domain-name-servers $dhcpd_conf->{domain_name_servers}[0];
+
+ range dynamic-bootp $lan.$dhcpd_conf->{dynamic_bootp}[0] $lan.$dhcpd_conf->{dynamic_bootp}[1];
+ default-lease-time $dhcpd_conf->{default_lease_time}[0];
+ max-lease-time $dhcpd_conf->{max_lease_time}[0];
+}
+));
+
+ #- put the interface for the dhcp server in the sysconfig-dhcp config, for the /etc/init.d script of dhcpd
+ log::explanations("Update network interfaces list for dhcpd server");
+ substInFile { s/^INTERFACES\n//; $_ .= qq(INTERFACES="$device"\n) if eof } $sysconf_dhcpd if !$::testing;
+ run_program::rooted($::prefix, $update_dhcp);
+}
+
+
+1;
diff --git a/lib/network/drakconnect.pm b/lib/network/drakconnect.pm
new file mode 100644
index 0000000..4f68ff0
--- /dev/null
+++ b/lib/network/drakconnect.pm
@@ -0,0 +1,26 @@
+package network::drakconnect;
+
+use common;
+use network::network;
+
+sub apply {
+ my ($in, $net, $modules_conf) = @_;
+ network::network::configure_network($net, $in, $modules_conf);
+}
+
+sub get_intf_ip {
+ my ($net, $interface) = @_;
+ my ($ip, $state, $mask);
+ if (-x "/sbin/ifconfig") {
+ local $_ = `LC_ALL=C LANGUAGE=C /sbin/ifconfig $interface`;
+ $ip = /inet addr:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/mso ? $1 : N("No IP");
+ $mask = /Mask:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/mso ? $1 : N("No Mask");
+ $state = /inet/ ? N("up") : N("down");
+ } else {
+ $ip = $net->{ifcfg}{$interface}{IPADDR};
+ $state = "n/a";
+ }
+ ($ip, $state, $mask);
+}
+
+1;
diff --git a/lib/network/drakconnect/.perl_checker b/lib/network/drakconnect/.perl_checker
new file mode 100644
index 0000000..80deab8
--- /dev/null
+++ b/lib/network/drakconnect/.perl_checker
@@ -0,0 +1 @@
+Basedir ../../..
diff --git a/lib/network/drakconnect/delete.pm b/lib/network/drakconnect/delete.pm
new file mode 100644
index 0000000..b8d0689
--- /dev/null
+++ b/lib/network/drakconnect/delete.pm
@@ -0,0 +1,68 @@
+package network::drakconnect::delete;
+
+use common;
+use wizards;
+use interactive;
+use network::connection::ethernet;
+
+sub del_intf {
+ my ($in, $net, $modules_conf) = @_;
+ my ($intf2delete, $failure);
+ if (!keys %{$net->{ifcfg}}) {
+ $in->ask_warn(N("Error"), N("No ethernet network adapter has been detected on your system. Please run the hardware configuration tool."));
+ return;
+ }
+ my @all_cards = network::connection::ethernet::get_eth_cards($modules_conf);
+ my %names = network::connection::ethernet::get_eth_cards_names(@all_cards);
+
+ my $wiz = wizards->new(
+ {
+ defaultimage => "drakconnect",
+ name => N("Remove a network interface"),
+ pages => {
+ welcome => {
+ no_back => 1,
+ name => N("Select the network interface to remove:"),
+ data => [ { label => N("Net Device"), val => \$intf2delete, allow_empty_list => 1,
+ list => [ keys %{$net->{ifcfg}} ],
+ format => sub {
+ my $type = network::tools::get_interface_type($net->{ifcfg}{$_[0]});
+ $names{$_[0]} || ($type ? "$type ($_[0])" : $_[0]);
+ }
+ }
+ ],
+ post => sub {
+ !$::testing and eval {
+ if (member($intf2delete, qw(adsl modem))) {
+ eval { rm_rf("/etc/ppp/peers/ppp0") };
+ eval { rm_rf("/etc/sysconfig/network-scripts/ifcfg-ppp0") };
+ }
+ if ($intf2delete eq 'adsl') {
+ eval { rm_rf("/etc/sysconfig/network-scripts/ifcfg-sagem") };
+ } elsif ($intf2delete eq 'isdn') {
+ eval { rm_rf("/etc/sysconfig/network-scripts/ifcfg-ippp0") };
+ } else {
+ system("ifdown $intf2delete");
+ eval { rm_rf("/etc/sysconfig/network-scripts/$intf2delete") };
+ eval { rm_rf("/etc/sysconfig/network-scripts/ifcfg-$intf2delete") };
+ }
+ };
+ $failure = $@;
+ network::network::reload_net_applet();
+ return "end";
+ },
+ },
+ end => {
+ name => sub {
+ $failure ?
+ N("An error occurred while deleting the \"%s\" network interface:\n\n%s", $intf2delete, $failure)
+ : N("Congratulations, the \"%s\" network interface has been successfully deleted", $intf2delete);
+ },
+ end => 1,
+ },
+ },
+ });
+ $wiz->safe_process($in);
+}
+
+1;
diff --git a/lib/network/drakconnect/edit.pm b/lib/network/drakconnect/edit.pm
new file mode 100644
index 0000000..4e1983b
--- /dev/null
+++ b/lib/network/drakconnect/edit.pm
@@ -0,0 +1,525 @@
+package network::drakconnect::edit;
+
+use ugtk2 qw(:create :dialogs :helpers :wrappers);
+use mygtk2 qw(gtknew);
+use common;
+use detect_devices;
+use run_program;
+use network::drakconnect;
+use network::adsl;
+use network::connection::ethernet;
+use network::connection::isdn;
+use network::modem;
+use network::network;
+
+sub manage {
+ my ($in, $net, $modules_conf) = @_;
+
+ my $p = {};
+ my ($interface_menu, $selected, $apply_button);
+ my $window = ugtk2->new('Manage Connection');
+ unless ($::isEmbedded) {
+ $window->{rwindow}->set_position('center');
+ $window->{rwindow}->set_title(N("Manage connections")); # translation availlable in mcc domain => we need merging
+ }
+
+ my $notebook = Gtk2::Notebook->new;
+ $notebook->set_property('show-tabs', 0);
+ $notebook->set_property('show-border', 0);
+
+ my @all_cards = network::connection::ethernet::get_eth_cards($modules_conf);
+ my %names = network::connection::ethernet::get_eth_cards_names(@all_cards);
+ foreach (keys %names) {
+ my $dev = detect_devices::is_lan_interface($_) ? $names{$_} : $_;
+ $p->{$dev} = {
+ name => $_ ,
+ intf => $net->{ifcfg}{$_}
+ };
+ }
+ while (my ($device, $interface) = each %{$net->{ifcfg}}) {
+ exists $names{$device} and next;
+ my $type = network::tools::get_interface_type($interface);
+ $p->{"$type ($device)"} = {
+ name => $device,
+ intf => $interface
+ };
+ }
+
+ $window->{rwindow}->add(gtkpack_(Gtk2::VBox->new,
+ 0, gtkpack__(Gtk2::HBox->new,
+ gtknew('Label', text => N("Device: "), alignment => [ 0, 0 ]),
+ $interface_menu = gtksignal_connect(Gtk2::ComboBox->new_text,
+ changed => sub {
+ $selected = $interface_menu->get_text;
+ $notebook->set_current_page($p->{$selected}{gui}{index});
+ },
+ ),
+ ),
+ 1, $notebook,
+ 0, create_okcancel(my $oc =
+ {
+ cancel_clicked => sub { $window->destroy; Gtk2->main_quit },
+ ok_clicked => sub {
+ if ($apply_button->get_property('sensitive')) {
+ save($in, $net, $modules_conf, $p, $apply_button);
+ }
+ $window->destroy;
+ Gtk2->main_quit;
+ },
+ },
+ undef, undef, '',
+ [ N("Help"), sub { run_program::raw({ detach => 1 }, 'drakhelp', '--id', 'internet-connection') } ],
+ [ N("Apply"), sub { save($in, $net, $modules_conf, $p, $apply_button) }, 0, 1 ],
+ ),
+ ),
+ );
+ $apply_button = $oc->{buttons}{N("Apply")};
+
+ each_index {
+ my ($name, $interface) = ($_, $p->{$_}{name});
+ $p->{$name}{gui}{index} = $::i;
+ $p->{$name}{intf} ||= { DEVICE => $interface };
+ build_tree($in, $net, $p->{$name}{intf}, $name);
+ build_notebook($net, \@all_cards, $p->{$name}{intf}, $p->{$name}{gui}, $apply_button, $name, $interface);
+ $notebook->append_page(gtkpack(Gtk2::VBox->new(0,0), $p->{$name}{gui}{notebook}));
+ } (sort keys %$p);
+
+ $interface_menu->set_popdown_strings(sort keys %$p);
+ $interface_menu->set_active(0);
+ $apply_button->set_sensitive(0);
+
+ $window->{rwindow}->show_all;
+ $window->main;
+}
+
+sub build_tree {
+ my ($in, $net, $intf, $interface) = @_;
+
+ if ($interface eq 'adsl') {
+ $intf->{pages} = { 'TCP/IP' => 1, 'DHCP' => 1, 'Account' => 1, 'Options' => 1, 'Information' => 1 };
+ network::adsl::adsl_probe_info($net);
+ $intf->{save} = sub {
+ $net->{type} = 'adsl';
+ network::adsl::adsl_conf_backend($in, $net);
+ };
+ }
+ elsif ($interface eq 'modem') {
+ $intf->{pages} = { 'TCP/IP' => 1, 'Account' => 1, 'Modem' => 1, 'Options' => 1 };
+ put_in_hash($intf, network::modem::ppp_read_conf());
+ $intf->{save} = sub { network::modem::ppp_configure($net, $in, $intf) };
+ }
+ elsif ($interface eq 'isdn') {
+ $intf->{pages} = { 'TCP/IP' => 1, 'Account' => 1, 'Modem' => 1, 'Options' => 1 };
+ network::connection::isdn::read_config($intf);
+ $intf->{save} = sub { network::connection::isdn::apply_config($in, $intf) };
+ }
+ else {
+ #- ethernet is default
+ $intf->{pages} = { 'TCP/IP' => 1, 'DHCP' => 1, if_(network::tools::get_interface_type($intf) eq "wifi", 'Wireless' => 1), 'Options' => 1, 'Information' => 1 };
+ }
+}
+
+sub build_notebook {
+ my ($net, $all_cards, $intf, $gui, $apply_button, $interface, $interface_name) = @_;
+
+ my $apply = sub { $apply_button->set_sensitive(1) };
+ my $is_ethernet = detect_devices::is_lan_interface($interface);
+
+ my $size_group = Gtk2::SizeGroup->new('horizontal');
+
+ if ($intf->{pages}{'TCP/IP'}) {
+ gtkpack__($gui->{sheet}{'TCP/IP'} = gtkset_border_width(Gtk2::VBox->new(0,10), 5),
+ gtknew('Title2', label => N("IP configuration")),
+ if_($is_ethernet,
+ gtkpack(Gtk2::HBox->new(1,0),
+ gtknew('Label_Left', text => N("Protocol")),
+ $gui->{intf}{BOOTPROTO} = gtksignal_connect(Gtk2::ComboBox->new_text, changed => sub {
+ return if !$_[0]->realized;
+ my $proto = $gui->{intf}{BOOTPROTO};
+ my $protocol = $intf->{BOOTPROTO} = { reverse %{$proto->{protocols}} }->{$proto->get_text};
+
+ foreach ($gui->{intf}{IPADDR}, $gui->{intf}{NETMASK}, $gui->{network}{GATEWAY}) {
+ $_->set_sensitive(to_bool($protocol eq "static"));
+ }
+ $gui->{sheet}{DHCP}->set_sensitive($intf->{BOOTPROTO} eq 'dhcp');
+ $apply->();
+ },
+ ),
+ ),
+ ),
+ gtkpack(Gtk2::HBox->new(1,0),
+ gtknew('Label_Left', text => N("IP address")),
+ gtksignal_connect($gui->{intf}{IPADDR} = Gtk2::Entry->new,
+ key_press_event => $apply),
+ ),
+ gtkpack(Gtk2::HBox->new(1,0),
+ gtknew('Label_Left', text => N("Netmask")),
+ gtksignal_connect($gui->{intf}{NETMASK} = Gtk2::Entry->new,
+ key_press_event => $apply),
+ ),
+ if_($is_ethernet,
+ gtkpack(Gtk2::HBox->new(1,0),
+ gtknew('Label_Left', text => N("Gateway")),
+ gtksignal_connect($gui->{network}{GATEWAY} = Gtk2::Entry->new,
+ key_press_event => $apply),
+ ),
+ ),
+ gtknew('Title2', label => N("DNS servers")),
+ gtknew('Label_Left', text => join(', ', grep { $_ } $intf->{dns1} || $net->{resolv}{dnsServer},
+ $intf->{dns2} || $net->{resolv}{dnsServer2},
+ $intf->{dns3} || $net->{resolv}{dnsServer3}),
+ ),
+ gtkpack(Gtk2::HBox->new(1,0),
+ gtknew('Label_Left', text => N("Search Domain")),
+ my $w2 = gtknew('Label_Left', text => $intf->{domain} || $net->{resolv}{DOMAINNAME} || 'none'),
+ ),
+ );
+ $size_group->add_widget($_) foreach $w2, $gui->{intf}{BOOTPROTO}, $gui->{intf}{IPADDR}, $gui->{intf}{NETMASK}, $gui->{network}{GATEWAY};
+
+ if ($is_ethernet) {
+ my $proto = $gui->{intf}{BOOTPROTO};
+ $proto->{protocols} = { none => N("none"), static => N("static"), dhcp => N("DHCP") };
+ $proto->set_popdown_strings(values %{$proto->{protocols}});
+ $proto->set_text($proto->{protocols}{$intf->{BOOTPROTO} || 'none'});
+ if ($intf->{BOOTPROTO} ne 'static') {
+ $_->set_sensitive(0) foreach $gui->{intf}{IPADDR}, $gui->{intf}{NETMASK}, $gui->{network}{GATEWAY};
+ }
+ } else {
+ $_->set_sensitive(0) foreach $gui->{intf}{IPADDR}, $gui->{intf}{NETMASK}, $gui->{network}{GATEWAY};
+ delete $gui->{intf}{BOOTPROTO};
+ }
+ !$intf->{IPADDR} and ($intf->{IPADDR}, $gui->{active}, $intf->{NETMASK}) = network::drakconnect::get_intf_ip($net, $interface_name);
+ $gui->{network}{$_}->set_text($net->{network}{$_}) foreach keys %{$gui->{network}};
+ }
+
+ if ($intf->{pages}{DHCP}) {
+ gtkpack(gtkset_border_width($gui->{sheet}{DHCP} = Gtk2::HBox->new(0,10), 5),
+ gtkpack__(gtkset_border_width(Gtk2::VBox->new(0,10), 5),
+ gtkpack__(Gtk2::HBox->new(1,0),
+ gtknew('Label_Left', text => N("DHCP client")),
+ gtksignal_connect($gui->{intf}{DHCP_CLIENT} = Gtk2::ComboBox->new_with_strings(\@network::connection::ethernet::dhcp_clients,
+ $intf->{DHCP_CLIENT} || $network::connection::ethernet::dhcp_clients[0]),
+ changed => $apply)),
+ gtksignal_connect($gui->{intf_bool}{NEEDHOSTNAME} = Gtk2::CheckButton->new(N("Assign host name from DHCP server (or generate a unique one)")), toggled => $apply),
+ gtkpack__(Gtk2::HBox->new(1,0),
+ gtknew('Label_Left', text => N("DHCP host name")),
+ gtksignal_connect($gui->{intf}{DHCP_HOSTNAME} = Gtk2::Entry->new,
+ key_press_event => $apply)),
+ gtkpack__(Gtk2::HBox->new(1,0),
+ gtknew('Label_Left', text => N("DHCP timeout (in seconds)")),
+ gtksignal_connect($gui->{intf}{DHCP_TIMEOUT} = Gtk2::Entry->new,
+ key_press_event => $apply)),
+ gtksignal_connect($gui->{intf_bool}{PEERDNS} = Gtk2::CheckButton->new(N("Get DNS servers from DHCP")), toggled => $apply),
+ gtksignal_connect($gui->{intf_bool}{PEERYP} = Gtk2::CheckButton->new(N("Get YP servers from DHCP")), toggled => $apply),
+ gtksignal_connect($gui->{intf_bool}{PEERNTPD} = Gtk2::CheckButton->new(N("Get NTPD servers from DHCP")), toggled => $apply),
+ ),
+ );
+ foreach (qw(NEEDHOSTNAME PEERDNS)) { #- default these settings to yes
+ defined $intf->{$_} or $intf->{$_} = "yes";
+ }
+ $gui->{intf}{$_}->set_text($intf->{$_}) foreach qw(DHCP_HOSTNAME DHCP_TIMEOUT);
+ $gui->{intf_bool}{$_}->set_active(text2bool($intf->{$_})) foreach qw(NEEDHOSTNAME PEERDNS PEERYP PEERNTPD);
+ $gui->{intf}{DHCP_CLIENT}->set_text($intf->{DHCP_CLIENT});
+ $gui->{sheet}{DHCP}->set_sensitive($intf->{BOOTPROTO} eq 'dhcp');
+ }
+ my $size_group2 = Gtk2::SizeGroup->new('horizontal');
+ $size_group2->add_widget($_) foreach $gui->{intf}{DHCP_HOSTNAME}, $gui->{intf}{DHCP_TIMEOUT}, $gui->{intf}{DHCP_CLIENT};
+
+ if ($intf->{pages}{Wireless}) {
+ gtkpack(gtkset_border_width($gui->{sheet}{Wireless} = Gtk2::HBox->new(0,10), 5),
+ gtkpack_(Gtk2::VBox->new(0,0),
+ map { (0, gtkpack_(Gtk2::VBox->new(0,0),
+ 1, Gtk2::Label->new($_->[0]),
+ 0, gtksignal_connect($gui->{intf}{$_->[1]} = Gtk2::Entry->new,
+ key_press_event => $apply),
+ ));
+ } ([ N("Operating Mode"), "WIRELESS_MODE" ],
+ [ N("Network name (ESSID)"), "WIRELESS_ESSID" ],
+ [ N("Network ID"), "WIRELESS_NWID" ],
+ [ N("Operating frequency"), "WIRELESS_FREQ" ],
+ [ N("Sensitivity threshold"), "WIRELESS_SENS" ],
+ [ N("Bitrate (in b/s)"), "WIRELESS_RATE" ]
+ ),
+ ),
+ Gtk2::VSeparator->new,
+ gtkpack_(Gtk2::VBox->new(0,0),
+ map { (0, gtkpack_(Gtk2::VBox->new(0,0),
+ 1, Gtk2::Label->new($_->[0]),
+ 0, gtksignal_connect($gui->{intf}{$_->[1]} = Gtk2::Entry->new,
+ key_press_event => $apply),
+ ));
+ } ([ N("Encryption key"), 'WIRELESS_ENC_KEY' ],
+ [ N("RTS/CTS"), 'WIRELESS_RTS' ],
+ [ N("Fragmentation"), 'WIRELESS_FRAG' ],
+ [ N("iwconfig command extra arguments"), 'WIRELESS_IWCONFIG' ],
+ [ N("iwspy command extra arguments"), 'WIRELESS_IWSPY' ],
+ [ N("iwpriv command extra arguments"), 'WIRELESS_IWPRIV' ],
+ ),
+ ),
+ );
+ }
+
+ if ($intf->{pages}{Options}) {
+ gtkpack__(gtkset_border_width($gui->{sheet}{Options} = Gtk2::VBox->new(0,10), 5),
+ $gui->{intf_bool}{ONBOOT} = gtksignal_connect(Gtk2::CheckButton->new(N("Start at boot")),
+ toggled => $apply),
+ if_($is_ethernet,
+ map { ($gui->{intf_bool}{$_->[0]} = gtksignal_connect(Gtk2::CheckButton->new($_->[1]),
+ toggled => $apply));
+ } (
+ [ "MII_NOT_SUPPORTED", N("Network Hotplugging") ],
+ ),
+ ),
+ if_($interface eq 'isdn',
+ gtkpack(Gtk2::HBox->new(0,0),
+ gtkpack__(Gtk2::VBox->new(0,0),
+ Gtk2::Label->new(N("Dialing mode")),
+ my @dialing_mode_radio = gtkradio(("auto") x 2, "manual"),
+ ),
+ Gtk2::VSeparator->new,
+ gtkpack__(Gtk2::VBox->new(0,0),
+ Gtk2::Label->new(N("Connection speed")),
+ my @speed_radio = gtkradio(("64 Kb/s") x 2, "128 Kb/s"),
+ ),
+ ),
+ gtkpack__(Gtk2::HBox->new(0,5),
+ Gtk2::Label->new(N("Connection timeout (in sec)")),
+ gtksignal_connect($gui->{intf}{huptimeout} = Gtk2::Entry->new,
+ key_press_event => $apply),
+ ),
+ ),
+ gtkpack__(Gtk2::HBox->new(0,1),
+ gtknew('Label_Left', text => N("Metric")),
+ gtksignal_connect(gtkset_text($gui->{intf}{METRIC} = Gtk2::Entry->new, $intf->{METRIC}),
+ key_press_event => $apply)),
+
+ );
+ $dialing_mode_radio[0]->signal_connect(toggled => sub { $gui->{intf_radio}{dialing_mode} = 'auto'; $apply->() });
+ $dialing_mode_radio[1]->signal_connect(toggled => sub { $gui->{intf_radio}{dialing_mode} = 'static'; $apply->() });
+ $speed_radio[0]->signal_connect(toggled => sub { $gui->{intf_radio}{speed} = '64'; $apply->() });
+ $speed_radio[1]->signal_connect(toggled => sub { $gui->{intf_radio}{speed} = '128'; $apply->() });
+ $gui->{intf_bool}{ONBOOT}->set_active($intf->{ONBOOT} eq 'yes' ? 1 : 0);
+ $gui->{intf_bool}{MII_NOT_SUPPORTED}->set_active($intf->{MII_NOT_SUPPORTED} eq 'no' ? 1 : 0);
+ }
+
+ if ($intf->{pages}{Account}) {
+ if ($interface_name =~ /^speedtouch|sagem$/) {
+ $gui->{description} = $interface_name eq 'speedtouch' ? 'Alcatel|USB ADSL Modem (Speed Touch)' : 'Analog Devices Inc.|USB ADSL modem';
+ }
+ gtkpack_(gtkset_border_width($gui->{sheet}{Account} = Gtk2::VBox->new(0,10), 5),
+ if_($interface eq 'modem',
+ 0, gtkpack(Gtk2::VBox->new(1,0),
+ gtkpack__(Gtk2::HBox->new, Gtk2::Label->new(N("Authentication"))),
+ gtkpack__(Gtk2::HBox->new, $gui->{intf}{auth} = gtksignal_connect(Gtk2::ComboBox->new_text,
+ changed => $apply)),
+ )),
+ map { (0, gtkpack(Gtk2::VBox->new(1,0),
+ gtkpack__(Gtk2::HBox->new, Gtk2::Label->new($_->[0])),
+ gtkpack__(Gtk2::HBox->new, $gui->{intf}{$_->[1]} = gtksignal_connect(Gtk2::Entry->new,
+ key_press_event => $apply)),
+ ),
+ );
+ } ([ N("Account Login (user name)"), 'login' ],
+ [ N("Account Password"), 'passwd' ],
+ if_($interface =~ /^(isdn|modem)$/, [ N("Provider phone number"), $1 eq 'modem' ? 'phone' : 'phone_out' ]),
+ ),
+ );
+
+ if ($interface eq 'modem') {
+ my %auth_methods = map_index { $::i => $_ } N("PAP"), N("Terminal-based"), N("Script-based"), N("CHAP"), N("PAP/CHAP");
+ $gui->{intf}{auth}->set_popdown_strings(sort values %auth_methods);
+ $gui->{intf}{auth}->set_text($auth_methods{$intf->{Authentication}});
+ }
+ $gui->{intf}{passwd}->set_visibility(0);
+ }
+
+ if ($intf->{pages}{Modem}) {
+ gtkpack(gtkset_border_width($gui->{sheet}{Modem} = Gtk2::HBox->new(0,10), 5),
+ if_($interface eq 'modem',
+ gtkpack__(Gtk2::VBox->new(0,5),
+ (map { (gtkpack(Gtk2::VBox->new(1,0),
+ gtkpack__(Gtk2::HBox->new, Gtk2::Label->new($_->[0])),
+ gtkpack__(Gtk2::HBox->new, $gui->{intf}{$_->[1]} = gtksignal_connect(Gtk2::ComboBox->new_text,
+ changed => $apply)),
+ ),
+ );
+ } ([ N("Flow control"), 'FlowControl' ],
+ [ N("Line termination"), 'Enter' ],
+ [ N("Connection speed"), 'Speed' ],
+ )),
+ # gtkpack(Gtk2::VBox->new(0,0), # no relative kppp option found :-(
+ # Gtk2::Label->new(N("Dialing mode")),
+ # gtkradio('', N("Tone dialing"), N("Pulse dialing")),
+ # ),
+ ),
+ Gtk2::VSeparator->new,
+ gtkpack__(Gtk2::VBox->new(0,10),
+ gtkpack__(Gtk2::HBox->new(0,5),
+ Gtk2::Label->new(N("Modem timeout")),
+ $gui->{intf}{Timeout} = gtksignal_connect(Gtk2::SpinButton->new(Gtk2::Adjustment->new($intf->{Timeout}, 0, 120, 1, 5, 0), 0, 0),
+ value_changed => $apply),
+ ),
+ gtksignal_connect($gui->{intf_bool}{UseLockFile} = Gtk2::CheckButton->new(N("Use lock file")),
+ toggled => $apply),
+ gtkpack__(Gtk2::HBox->new, gtksignal_connect($gui->{intf_bool}{WaitForDialTone} = Gtk2::CheckButton->new(N("Wait for dialup tone before dialing")),
+ toggled => $apply)),
+ gtkpack__(Gtk2::HBox->new(0,5),
+ Gtk2::Label->new(N("Busy wait")),
+ $gui->{intf}{BusyWait} = gtksignal_connect(Gtk2::SpinButton->new(Gtk2::Adjustment->new($intf->{BusyWait}, 0, 120, 1, 5, 0), 0, 0),
+ value_changed => $apply),
+ ),
+ gtkpack__(Gtk2::HBox->new(0,5),
+ Gtk2::Label->new(N("Modem sound")),
+ gtkpack__(Gtk2::VBox->new(0,5), my @volume_radio = gtkradio('', N("Enable"), N("Disable"))),
+ ),
+ ),
+ ),
+ if_($interface eq 'isdn',
+ gtkpack_(Gtk2::VBox->new(0,0),
+ map { (0, gtkpack(Gtk2::VBox->new(1,0),
+ gtkpack__(Gtk2::HBox->new, Gtk2::Label->new($_->[0])),
+ gtkpack__(Gtk2::HBox->new, $gui->{intf}{$_->[1]} = gtksignal_connect(Gtk2::Entry->new,
+ key_press_event => $apply)),
+ ),
+ );
+ } ([ N("Card IRQ"), 'irq' ],
+ [ N("Card mem (DMA)"), 'mem' ],
+ [ N("Card IO"), 'io' ],
+ [ N("Card IO_0"), 'io0' ],
+ ),
+ ),
+ Gtk2::VSeparator->new,
+ gtkpack__(Gtk2::VBox->new(0,0),
+ Gtk2::Label->new(N("Protocol")),
+ my @protocol_radio = gtkradio('', N("European protocol (EDSS1)"),
+ N("Protocol for the rest of the world\nNo D-Channel (leased lines)")),
+ ),
+ ),
+ );
+ $protocol_radio[0]->signal_connect(toggled => sub { $gui->{intf_radio}{protocol} = 2; $apply->() });
+ $protocol_radio[1]->signal_connect(toggled => sub { $gui->{intf_radio}{protocol} = 3; $apply->() });
+ $volume_radio[0]->signal_connect(toggled => sub { $gui->{intf_radio}{Volume} = 1; $apply->() });
+ $volume_radio[1]->signal_connect(toggled => sub { $gui->{intf_radio}{Volume} = 0; $apply->() });
+ $gui->{intf}{FlowControl}->set_popdown_strings('Hardware [CRTSCTS]', 'Software [XON/XOFF]', 'None');
+ $gui->{intf}{Enter}->set_popdown_strings('CR', 'CF', 'CR/LF');
+ $gui->{intf}{Speed}->set_popdown_strings('2400', '9600', '19200', '38400', '57600', '115200');
+ }
+
+ if ($intf->{pages}{Information}) {
+ my ($info) = $gui->{description} ?
+ find { $_->{description} eq $gui->{description} } detect_devices::probeall : network::connection::ethernet::mapIntfToDevice($interface_name);
+ my @intfs = grep { $interface_name eq $_->[0] } @$all_cards;
+ if (is_empty_hash_ref($info) && @intfs == 1) {
+ my $driver = $intfs[0][1];
+ my @cards = grep { $_->{driver} eq $driver } detect_devices::probeall();
+ @cards == 1 and $info = $cards[0];
+ }
+
+ gtkpack(gtkset_border_width($gui->{sheet}{Information} = Gtk2::VBox->new(0,10), 5),
+ gtktext_insert(Gtk2::TextView->new,
+ join('',
+ map { $_->[0] . ": \x{200e}" . $_->[1] . "\n" } (
+ [ N("Vendor"), split('\|', $info->{description}) ],
+ [ N("Description"), reverse split('\|', $info->{description}) ],
+ [ N("Media class"), $info->{media_type} || '-' ],
+ [ N("Module name"), $info->{driver} || '-' ],
+ [ N("Mac Address"), c::get_hw_address($interface_name) || '-' ],
+ [ N("Bus"), $info->{bus} || '-' ],
+ [ N("Location on the bus"), $info->{pci_bus} || '-' ],
+ )
+ )
+ ),
+ );
+ }
+
+ foreach (keys %{$gui->{intf}}) {
+ next if ref($gui->{intf}{$_}) !~ /Gtk2::(ComboBox|Entry)/;
+ # skip unset fields:
+ next if !$intf->{$_};
+ # special case b/c of translation:
+ next if member($_, qw(BOOTPROTO ));
+ if ($_ eq "FlowControl") {
+ # kppp is writing translated strings :-( (eg: s/Software/Logiciel/):
+ # (let's hope that all translations use 'CRTSCTS' and 'XON/OFF' as substring)
+ $gui->{intf}{$_}->set_text('Hardware [CRTSCTS]') if $intf->{$_} =~ /CRTSCTS/;
+ $gui->{intf}{$_}->set_text('Software [XON/XOFF]') if $intf->{$_} =~ m!XON/XOFF!;
+ } else {
+ $gui->{intf}{$_}->set_text($intf->{$_});
+ }
+ }
+
+ $gui->{notebook} = Gtk2::Notebook->new;
+ populate_notebook($gui->{notebook}, $gui);
+}
+
+sub populate_notebook {
+ my ($notebook, $gui) = @_;
+ foreach ('TCP/IP', 'DHCP', 'Account', 'Wireless', 'Modem', 'Options', 'Information') {
+ !$gui->{sheet}{$_} and next;
+ $notebook->append_page($gui->{sheet}{$_}, Gtk2::Label->new(translate($_)));
+ }
+}
+
+sub save {
+ my ($in, $net, $modules_conf, $p, $apply_button) = @_;
+
+ my $dialog = _create_dialog(N("Please wait"));
+ gtkpack($dialog->vbox,
+ gtkshow(Gtk2::Label->new(N("Please Wait... Applying the configuration"))));
+ $dialog->show_all;
+ gtkset_mousecursor_wait();
+
+ Glib::Timeout->add(200, sub {
+ gtkflush();
+ delete $net->{network}{GATEWAY};
+ foreach (keys %$p) {
+ save_notebook($in, $net, $p->{$_}{intf}, $p->{$_}{gui}) or return;
+ $p->{$_}{intf}{save} and $p->{$_}{intf}{save}->();
+ }
+ network::drakconnect::apply($in, $net, $modules_conf);
+ system("/etc/rc.d/init.d/network restart");
+ $dialog->response(0);
+ });
+ $dialog->run;
+
+ $apply_button->set_sensitive(0);
+ gtkset_mousecursor_normal();
+ $dialog->destroy;
+}
+
+sub save_notebook {
+ my ($in, $net, $intf, $gui) = @_;
+
+ if ($gui->{network}{GATEWAY}->is_sensitive && $gui->{network}{GATEWAY}->get_text) {
+ $net->{network}{GATEWAY} = $gui->{network}{GATEWAY}->get_text;
+ }
+ $gui->{intf}{$_} and $intf->{$_} = $gui->{intf}{$_}->get_text foreach keys %{$gui->{intf}};
+ $gui->{intf_radio}{$_} and $intf->{$_} = $gui->{intf_radio}{$_} foreach keys %{$gui->{intf_radio}};
+ $intf->{$_} = bool2yesno($gui->{intf_bool}{$_}->get_active) foreach keys %{$gui->{intf_bool}};
+ $gui->{intf_bool}{MII_NOT_SUPPORTED} and $intf->{MII_NOT_SUPPORTED} = bool2yesno(!$gui->{intf_bool}{MII_NOT_SUPPORTED}->get_active);
+
+ if (my $proto = $gui->{intf}{BOOTPROTO}) {
+ $intf->{BOOTPROTO} = { reverse %{$proto->{protocols}} }->{$proto->get_text};
+ }
+ if ($intf->{BOOTPROTO} eq 'static') {
+ if (!is_ip($intf->{IPADDR})) {
+ $in->ask_warn(N("Error"), N("IP address should be in format 1.2.3.4"));
+ return 0;
+ }
+ if (!is_ip($intf->{NETMASK})) {
+ $in->ask_warn(N("Error"), N("Netmask should be in format 255.255.224.0"));
+ return 0;
+ }
+ }
+
+ delete $intf->{IPADDR} if $intf->{IPADDR} eq N("No IP");
+ delete $intf->{NETMASK} if $intf->{NETMASK} eq N("No Mask");
+
+ if ($net->{network}{GATEWAY} && !is_ip($net->{network}{GATEWAY})) {
+ $in->ask_warn(N("Error"), N("Gateway address should be in format 1.2.3.4"));
+ return 0;
+ }
+ 1;
+}
+
+1;
diff --git a/lib/network/drakconnect/global.pm b/lib/network/drakconnect/global.pm
new file mode 100644
index 0000000..ad59c2a
--- /dev/null
+++ b/lib/network/drakconnect/global.pm
@@ -0,0 +1,107 @@
+package network::drakconnect::global;
+
+use ugtk2 qw(:create :dialogs :helpers :wrappers);
+use mygtk2 qw(gtknew);
+use common;
+use network::drakconnect;
+use network::test;
+
+my $net_test;
+sub update_network_status {
+ my ($int_state) = @_;
+ unless ($net_test) {
+ $net_test = network::test->new;
+ $net_test->start;
+ }
+ if ($net_test->is_done) {
+ my $isconnected = $net_test->is_connected;
+ $int_state->set($isconnected ? N("Connected") : N("Not connected"));
+ $net_test->start;
+ }
+ 1;
+}
+
+sub configure_net {
+ my ($in, $net, $modules_conf) = @_;
+ my $int_state;
+ my $int_label = Gtk2::WrappedLabel->new($net->{type} eq 'lan' ? N("Gateway:") : N("Interface:"));
+ my $int_name = Gtk2::Label->new($net->{type} eq 'lan' ? $net->{network}{GATEWAY} : $net->{net_interface});
+
+ my $dialog = ugtk2->new(N("Internet connection configuration"));
+ my $exit_dialogsub = sub { Gtk2->main_quit };
+ if (!$net->{type}) {
+ $in->ask_warn(
+ N("Warning"),
+ N("You do not have any configured Internet connection.
+Run the \"%s\" assistant from the Mandriva Linux Control Center", N("Set up a new network interface (LAN, ISDN, ADSL, ...)")));
+ return;
+ }
+ unless ($::isEmbedded) {
+ $dialog->{rwindow}->set_position('center');
+ $dialog->{rwindow}->set_size_request(-1, -1);
+ $dialog->{rwindow}->set_icon(gtkcreate_pixbuf("drakconnect"));
+ }
+ $dialog->{rwindow}->signal_connect(delete_event => $exit_dialogsub);
+
+ my $param_vbox = Gtk2::VBox->new(0,0);
+ my $i = 0;
+
+ my @conf_data = (
+ [ N("Host name (optional)"), \$net->{network}{HOSTNAME} ],
+ [ N("First DNS Server (optional)"), \$net->{resolv}{dnsServer} ],
+ [ N("Second DNS Server (optional)"), \$net->{resolv}{dnsServer2} ],
+ [ N("Third DNS server (optional)"), \$net->{resolv}{dnsServer3} ],
+ );
+ my @infos;
+ gtkpack($param_vbox,
+ create_packtable({},
+ map {
+ my $c;
+ if (defined $_->[2]) {
+ $c = Gtk2::Combo->new;
+ $c->set_popdown_strings(@{$_->[2]});
+ $infos[2*$i+1] = $c->entry;
+ } else {
+ $c = $infos[2*$i+1] = Gtk2::Entry->new;
+ }
+ $infos[2*$i+1]->set_text(${$_->[1]});
+ $i++;
+ [ Gtk2::WrappedLabel->new($_->[0]), $c ];
+ } @conf_data
+ )
+ );
+
+ $dialog->{rwindow}->add(gtkpack_(Gtk2::VBox->new,
+ 0, Gtk2::Label->new(N("Internet Connection Configuration")),
+ 1, gtkadd(gtkcreate_frame(N("Internet access")),
+ gtkset_border_width(create_packtable({ col_spacings => 5, row_spacings => 5, homogenous => 1 },
+ [ Gtk2::WrappedLabel->new(N("Connection type: ")),
+ Gtk2::WrappedLabel->new(translate($net->{type})) ],
+ [ $int_label, $int_name ],
+ [ Gtk2::WrappedLabel->new(N("Status:")),
+ $int_state = Gtk2::WrappedLabel->new(N("Testing your connection...")) ]
+ ),
+ 5),
+ ),
+ 1, gtkadd(gtkcreate_frame(N("Parameters")), gtkset_border_width($param_vbox, 5)),
+ 0, gtkpack(create_hbox('edge'),
+ gtksignal_connect(Gtk2::Button->new(N("Cancel")), clicked => $exit_dialogsub),
+ gtksignal_connect(Gtk2::Button->new(N("Ok")), clicked => sub {
+ foreach my $i (0..$#conf_data) {
+ ${$conf_data[$i][1]} = $infos[2*$i+1]->get_text;
+ }
+ network::drakconnect::apply($in, $net, $modules_conf);
+ $exit_dialogsub->();
+ }),
+ ),
+ ),
+ );
+
+ $dialog->{rwindow}->show_all;
+ my $update = sub { update_network_status($int_state) };
+ $update->();
+ Glib::Timeout->add(2000, $update);
+ $dialog->main;
+}
+
+1;
diff --git a/lib/network/drakfirewall.pm b/lib/network/drakfirewall.pm
new file mode 100644
index 0000000..5746ae7
--- /dev/null
+++ b/lib/network/drakfirewall.pm
@@ -0,0 +1,372 @@
+package network::drakfirewall; # $Id$
+
+use strict;
+use diagnostics;
+
+use network::shorewall;
+use common;
+use network::nfs;
+use network::network;
+
+my @all_servers =
+(
+ {
+ name => N_("Web Server"),
+ pkg => 'apache apache-mod_perl boa lighttpd thttpd',
+ ports => '80/tcp 443/tcp',
+ },
+ {
+ name => N_("Domain Name Server"),
+ pkg => 'bind dnsmasq mydsn',
+ ports => '53/tcp 53/udp',
+ },
+ {
+ name => N_("SSH server"),
+ pkg => 'openssh-server',
+ ports => '22/tcp',
+ },
+ {
+ name => N_("FTP server"),
+ pkg => 'ftp-server-krb5 wu-ftpd proftpd pure-ftpd',
+ ports => '20/tcp 21/tcp',
+ },
+ {
+ name => N_("DHCP Server"),
+ pkg => 'dhcp-server udhcpd',
+ ports => '67/udp 68/udp',
+ hide => 1,
+ },
+ {
+ name => N_("Mail Server"),
+ pkg => 'sendmail postfix qmail exim',
+ ports => '25/tcp',
+ },
+ {
+ name => N_("POP and IMAP Server"),
+ pkg => 'imap courier-imap-pop',
+ ports => '109/tcp 110/tcp 143/tcp',
+ },
+ {
+ name => N_("Telnet server"),
+ pkg => 'telnet-server-krb5',
+ ports => '23/tcp',
+ hide => 1,
+ },
+ {
+ name => N_("NFS Server"),
+ pkg => 'nfs-utils nfs-utils-clients',
+ ports => '111/tcp 111/udp 2049/tcp 2049/udp ' . network::nfs::list_nfs_ports(),
+ hide => 1,
+ prepare => sub { network::nfs::write_nfs_ports(network::nfs::read_nfs_ports()); },
+ restart => 'nfs-common nfs-server',
+ },
+ {
+ name => N_("Windows Files Sharing (SMB)"),
+ pkg => 'samba-server',
+ ports => '137/tcp 137/udp 138/tcp 138/udp 139/tcp 139/udp 445/tcp 445/udp 1024:1100/tcp 1024:1100/udp',
+ hide => 1,
+ },
+ {
+ name => N_("Bacula backup"),
+ pkg => 'bacula-fd bacula-sd bacula-dir-common',
+ ports => '9101:9103/tcp',
+ hide => 1,
+ },
+ {
+ name => N_("Syslog network logging"),
+ pkg => 'rsyslog syslog-ng',
+ ports => '514/udp',
+ hide => 1,
+ },
+ {
+ name => N_("CUPS server"),
+ pkg => 'cups',
+ ports => '631/tcp 631/udp',
+ hide => 1,
+ },
+ {
+ name => N_("MySQL server"),
+ pkg => 'mysql',
+ ports => '3306/tcp 3306/udp',
+ hide => 1,
+ },
+ {
+ name => N_("PostgreSQL server"),
+ pkg => 'postgresql8.2 postgresql8.3',
+ ports => '5432/tcp 5432/udp',
+ hide => 1,
+ },
+ {
+ name => N_("Echo request (ping)"),
+ ports => '8/icmp',
+ force_default_selection => 0,
+ },
+ {
+ name => N_("Network services autodiscovery (zeroconf and slp)"),
+ ports => '5353/udp 427/udp',
+ pkg => 'avahi cups openslp',
+ },
+ {
+ name => N_("BitTorrent"),
+ ports => '6881:6999/tcp',
+ hide => 1,
+ pkg => 'bittorrent deluge ktorrent transmission vuze rtorrent ctorrent',
+ },
+ {
+ name => N_("Windows Mobile device synchronization"),
+ pkg => 'synce-hal',
+ ports => '990/tcp 999/tcp 5678/tcp 5679/udp 26675/tcp',
+ hide => 1,
+ },
+);
+
+my @ifw_rules = (
+ {
+ name => N_("Port scan detection"),
+ ifw_rule => 'psd',
+ },
+);
+
+# global network configuration
+my $net = {};
+network::network::read_net_conf($net);
+
+sub port2server {
+ my ($port) = @_;
+ find {
+ any { $port eq $_ } split(' ', $_->{ports});
+ } @all_servers;
+}
+
+sub check_ports_syntax {
+ my ($ports) = @_;
+ foreach (split ' ', $ports) {
+ my ($nb, $range, $nb2) = m!^(\d+)(:(\d+))?/(tcp|udp|icmp)$! or return $_;
+ foreach my $port ($nb, if_($range, $nb2)) {
+ 1 <= $port && $port <= 65535 or return $_;
+ }
+ $nb < $nb2 or return $_ if $range;
+ }
+ '';
+}
+
+sub to_ports {
+ my ($servers, $unlisted) = @_;
+ join(' ', (map { $_->{ports} } @$servers), if_($unlisted, $unlisted));
+}
+
+sub from_ports {
+ my ($ports) = @_;
+
+ my @l;
+ my @unlisted;
+ foreach (split ' ', $ports) {
+ if (my $s = port2server($_)) {
+ push @l, $s;
+ } else {
+ push @unlisted, $_;
+ }
+ }
+ [ uniq(@l) ], join(' ', @unlisted);
+}
+
+sub default_from_pkgs {
+ my ($do_pkgs) = @_;
+ my @pkgs = $do_pkgs->are_installed(map { split ' ', $_->{pkg} } @all_servers);
+ [ grep {
+ my $s = $_;
+ exists $s->{force_default_selection} ?
+ $s->{force_default_selection} :
+ any { member($_, @pkgs) } split(' ', $s->{pkg});
+ } @all_servers ];
+}
+
+sub default_ports {
+ my ($do_pkgs) = @_;
+ to_ports(default_from_pkgs($do_pkgs), '');
+}
+
+sub get_ports() {
+ my $shorewall = network::shorewall::read() or return;
+ $shorewall->{ports};
+}
+
+sub set_ports {
+ my ($do_pkgs, $disabled, $ports, $log_net_drop, $o_in) = @_;
+
+ if (!$disabled || -x "$::prefix/sbin/shorewall") {
+ $do_pkgs->ensure_binary_is_installed('shorewall', 'shorewall', $::isInstall) or return;
+ my $shorewall = network::shorewall::read(!$disabled && $o_in);
+ if (!$shorewall) {
+ log::l("unable to read shorewall configuration, skipping installation");
+ return;
+ }
+
+ $shorewall->{disabled} = $disabled;
+ $shorewall->{ports} = $ports;
+ $shorewall->{log_net_drop} = $log_net_drop;
+ log::l($disabled ? "disabling shorewall" : "configuring shorewall to allow ports: $ports");
+ network::shorewall::write($shorewall, $o_in);
+ }
+}
+
+sub get_conf {
+ my ($in, $disabled, $o_ports) = @_;
+
+ my $possible_servers = default_from_pkgs($in->do_pkgs);
+ $_->{hide} = 0 foreach @$possible_servers;
+
+ if ($o_ports) {
+ $disabled, from_ports($o_ports);
+ } elsif (my $shorewall = network::shorewall::read()) {
+ $shorewall->{disabled}, from_ports($shorewall->{ports}), $shorewall->{log_net_drop};
+ } else {
+ $in->ask_okcancel(N("Firewall configuration"), N("drakfirewall configurator
+
+This configures a personal firewall for this Mandriva Linux machine.
+For a powerful and dedicated firewall solution, please look to the
+specialized Mandriva Security Firewall distribution."), 1) or return;
+
+ $in->ask_okcancel(N("Firewall configuration"), N("drakfirewall configurator
+
+Make sure you have configured your Network/Internet access with
+drakconnect before going any further."), 1) or return;
+
+ $disabled, $possible_servers, '';
+ }
+}
+
+sub choose_allowed_services {
+ my ($in, $disabled, $servers, $unlisted, $log_net_drop) = @_;
+
+ $_->{on} = 0 foreach @all_servers;
+ $_->{on} = 1 foreach @$servers;
+ my @l = grep { $_->{on} || !$_->{hide} } @all_servers;
+
+ $in->ask_from_({
+ title => N("Firewall"),
+ icon => $network::shorewall::firewall_icon,
+ if_(!$::isEmbedded, banner_title => N("Firewall")),
+ advanced_messages => N("You can enter miscellaneous ports.
+Valid examples are: 139/tcp 139/udp 600:610/tcp 600:610/udp.
+Have a look at /etc/services for information."),
+ callbacks => {
+ complete => sub {
+ if (my $invalid_port = check_ports_syntax($unlisted)) {
+ $in->ask_warn('', N("Invalid port given: %s.
+The proper format is \"port/tcp\" or \"port/udp\",
+where port is between 1 and 65535.
+
+You can also give a range of ports (eg: 24300:24350/udp)", $invalid_port));
+ return 1;
+ }
+ },
+ } },
+ [
+ { label => N("Which services would you like to allow the Internet to connect to?"), title => 1 },
+ if_($net->{PROFILE} && network::network::netprofile_count() > 0, { label => N("Those settings will be saved for the network profile <b>%s</b>", $net->{PROFILE}) }),
+ { text => N("Everything (no firewall)"), val => \$disabled, type => 'bool' },
+ (map { { text => translate($_->{name}), val => \$_->{on}, type => 'bool', disabled => sub { $disabled } } } @l),
+ { label => N("Other ports"), val => \$unlisted, advanced => 1, disabled => sub { $disabled } },
+ { text => N("Log firewall messages in system logs"), val => \$log_net_drop, type => 'bool', advanced => 1, disabled => sub { $disabled } },
+ ]) or return;
+
+ $disabled, [ grep { $_->{on} } @l ], $unlisted, $log_net_drop;
+}
+
+sub set_ifw {
+ my ($do_pkgs, $enabled, $rules, $ports) = @_;
+ if ($enabled) {
+ $do_pkgs->ensure_is_installed('mandi-ifw', '/etc/ifw/start', $::isInstall) or return;
+
+ my $ports_by_proto = network::shorewall::ports_by_proto($ports);
+ output_with_perm("$::prefix/etc/ifw/rules", 0644,
+ (map { "source /etc/ifw/rules.d/$_\n" } @$rules),
+ map {
+ my $proto = $_;
+ map {
+ my $multiport = /:/ && " -m multiport";
+ "iptables -A Ifw -m state --state NEW -p $proto$multiport --dport $_ -j IFWLOG --log-prefix NEW\n";
+ } @{$ports_by_proto->{$proto}};
+ } intersection([ qw(tcp udp) ], [ keys %$ports_by_proto ]),
+ );
+ }
+
+ substInFile {
+ undef $_ if $_ eq "INCLUDE /etc/ifw/rules", "iptables -I INPUT 2 -j Ifw";
+ } "$::prefix/etc/shorewall/start";
+ network::shorewall::set_in_file('start', $enabled, "INCLUDE /etc/ifw/start", "INCLUDE /etc/ifw/rules", "iptables -I INPUT 1 -j Ifw");
+ network::shorewall::set_in_file('stop', $enabled, "iptables -D INPUT -j Ifw", "INCLUDE /etc/ifw/stop");
+}
+
+sub choose_watched_services {
+ my ($in, $servers, $unlisted) = @_;
+
+ my @l = (@ifw_rules, @$servers, map { { ports => $_ } } split(' ', $unlisted));
+ my $enabled = 1;
+ $_->{ifw} = 1 foreach @l;
+
+ $in->ask_from_({
+ icon => $network::shorewall::firewall_icon,
+ if_(!$::isEmbedded, banner_title => N("Interactive Firewall")),
+ messages =>
+ N("You can be warned when someone accesses to a service or tries to intrude into your computer.
+Please select which network activities should be watched."),
+ title => N("Interactive Firewall"),
+ },
+ [
+ { text => N("Use Interactive Firewall"), val => \$enabled, type => 'bool' },
+ map { {
+ text => (exists $_->{name} ? translate($_->{name}) : $_->{ports}),
+ val => \$_->{ifw},
+ type => 'bool', disabled => sub { !$enabled },
+ } } @l,
+ ]) or return;
+ my ($rules, $ports) = partition { exists $_->{ifw_rule} } grep { $_->{ifw} } @l;
+ set_ifw($in->do_pkgs, $enabled, [ map { $_->{ifw_rule} } @$rules ], to_ports($ports));
+
+ # return something to say that we are done ok
+ $rules, $ports;
+}
+
+sub main {
+ my ($in, $disabled) = @_;
+
+ ($disabled, my $servers, my $unlisted, my $log_net_drop) = get_conf($in, $disabled) or return;
+
+ ($disabled, $servers, $unlisted, $log_net_drop) = choose_allowed_services($in, $disabled, $servers, $unlisted, $log_net_drop) or return;
+
+ my $system_file = '/etc/sysconfig/drakx-net';
+ my %global_settings = getVarsFromSh($system_file);
+
+ if (!$disabled && (!defined($global_settings{IFW}) || text2bool($global_settings{IFW}))) {
+ choose_watched_services($in, $servers, $unlisted) or return;
+ }
+
+ # preparing services when required
+ foreach (@$servers) {
+ exists $_->{prepare} and $_->{prepare}();
+ }
+
+ my $ports = to_ports($servers, $unlisted);
+
+ set_ports($in->do_pkgs, $disabled, $ports, $log_net_drop, $in) or return;
+
+ # restart mandi
+ require services;
+ services::is_service_running("mandi") and services::restart("mandi");
+
+ # restarting services if needed
+ foreach my $service (@$servers) {
+ if ($service->{restart}) {
+ services::is_service_running($_) and services::restart($_) foreach split(' ', $service->{restart});
+ }
+ }
+
+ # clearing pending ifw notifications in net_applet
+ system('killall -s SIGUSR1 net_applet');
+
+ ($disabled, $ports);
+}
+
+1;
diff --git a/lib/network/drakroam.pm b/lib/network/drakroam.pm
new file mode 100755
index 0000000..9ff8189
--- /dev/null
+++ b/lib/network/drakroam.pm
@@ -0,0 +1,136 @@
+package network::drakroam;
+
+# drakroam: wireless network roaming GUI
+# Austin Acton, 2004 <austin@mandriva.org>
+# Olivier Blin, 2005-2006 <oblin@mandriva.com>
+# Licensed under the GPL
+
+use strict;
+
+use common;
+use interactive;
+use mygtk2;
+use ugtk2 qw(:create :helpers :wrappers);
+use network::connection;
+use network::connection_manager;
+use network::connection::wireless;
+use network::connection::cellular_card;
+
+sub update_connections_list {
+ my ($droam) = @_;
+
+ $droam->{gui}{model}->set($droam->{gui}{model}->append, 0, $droam->{gui}{empty_pixbuf} , 1, N("No device found")) unless @{$droam->{all_connections}};
+ $droam->{gui}{model}->set($droam->{gui}{model}->append,
+ 0, gtknew('Pixbuf', file => $_->get_type_icon)->scale_simple($droam->{gui}{pixbuf_size}, $droam->{gui}{pixbuf_size}, 'hyper'),
+ 1, $_->get_description) foreach @{$droam->{all_connections}};
+ my $index = $droam->{connection} ?
+ eval { find_index { $_ == $droam->{connection} } @{$droam->{all_connections}} }
+ : 0;
+ $droam->{gui}{connections_combo}->set_active($index) if defined $index;
+}
+
+sub get_connection {
+ my ($droam) = @_;
+
+ @{$droam->{all_connections}} or return;
+ my $index = $droam->{gui}{connections_combo}->get_active;
+ defined $index && $droam->{all_connections}[$index];
+}
+
+sub select_connection {
+ my ($droam) = @_;
+
+ $droam->set_connection(get_connection($droam));
+ $droam->check_setup || $droam->setup_connection if $droam->{connection};
+ update_on_connection_change($droam);
+}
+
+sub update_on_connection_change {
+ my ($droam) = @_;
+ return if !($droam->{connection} && $droam->check_setup);
+ $droam->{gui}{buttons}{refresh}->set_sensitive(to_bool($droam->{connection}))
+ if $droam->{gui}{buttons}{refresh};
+ $droam->update_networks;
+}
+
+sub create_drakroam_gui {
+ my ($droam, $dbus, $title, $icon) = @_;
+
+ $droam->{gui}{model} = Gtk2::ListStore->new('Gtk2::Gdk::Pixbuf', 'Glib::String');
+ $droam->{gui}{connections_combo} = Gtk2::ComboBox->new($droam->{gui}{model});
+ my $pix_r = Gtk2::CellRendererPixbuf->new;
+ $droam->{gui}{connections_combo}->pack_start($pix_r, 0,);
+ $droam->{gui}{connections_combo}->add_attribute($pix_r, pixbuf => 0);
+ my $text_r = Gtk2::CellRendererText->new;
+ $droam->{gui}{connections_combo}->pack_start($text_r, 1);
+ $droam->{gui}{connections_combo}->add_attribute($text_r, text => 1);
+
+ $droam->{gui}{pixbuf_size} = 32;
+ $droam->{gui}{empty_pixbuf} = Gtk2::Gdk::Pixbuf->new('rgb', 1, 8, $droam->{gui}{pixbuf_size}, $droam->{gui}{pixbuf_size});
+ $droam->{gui}{empty_pixbuf}->fill(0);
+
+ my $status_bar = Gtk2::Statusbar->new;
+ my $status_bar_cid = $status_bar->get_context_id("Network event");
+ $droam->{on_network_event} = sub {
+ my ($message) = @_;
+ my $m_id = $status_bar->push($status_bar_cid, $message);
+ Glib::Timeout->add(20000, sub { $status_bar->remove($status_bar_cid, $m_id); 0 });
+ };
+
+ (undef, my $rootwin_height) = gtkroot()->get_size();
+ my $scrolled_height = $rootwin_height > 480 ? 300 : 225;
+ gtkadd($droam->{gui}{w}{window},
+ gtknew('VBox', spacing => 5, children => [
+ $::isEmbedded ? () : (0, Gtk2::Banner->new($icon, $title)),
+ 0, gtknew('HBox', children_tight => [ gtknew('Label_Left', text => N("Device: "), alignment => [ 0.5, 0.5 ]),
+ gtksignal_connect($droam->{gui}{connections_combo}, changed => sub { select_connection($droam) }) ]),
+ 1, gtknew('ScrolledWindow', width => 500, height => $scrolled_height, child => $droam->{gui}{networks_list}),
+ 0, gtknew('HButtonBox', layout => 'edge', children_loose => [
+ $droam->{gui}{buttons}{configure} = gtknew('Button', text => N("Configure"), clicked => sub { $droam->configure_connection }),
+ $droam->{gui}{buttons}{connect_start} = gtknew('Button', text => N("Connect"), relief => 'half', clicked => sub { $droam->start_connection }),
+ $droam->{gui}{buttons}{connect_stop} = gtknew('Button', text => N("Disconnect"), relief => 'half', clicked => sub { $droam->stop_connection }),
+ $droam->{gui}{buttons}{refresh} = gtknew('Button', text => N("Refresh"), clicked => sub { $droam->update_networks }),
+ gtknew('Button', text => N("Quit"), clicked => sub { Gtk2->main_quit })
+ ]),
+ 0, $status_bar,
+ ]),
+ );
+}
+
+sub main {
+ my ($in, $net, $dbus, $o_interface, $o_ap) = @_;
+
+ my $title = N("Wireless connection");
+ my $icon = '/usr/share/mcc/themes/default/drakroam-mdk.png';
+
+ $ugtk2::wm_icon = $icon;
+ my $w = ugtk2->new($title);
+ #- so that transient_for is defined, for wait messages and popups to be centered
+ $::main_window = $w->{real_window};
+
+ my $pixbufs = network::connection_manager::create_pixbufs();
+ my $droam = network::connection_manager->new($in, $net, $w, $pixbufs);
+ $droam->create_networks_list;
+ create_drakroam_gui($droam, $dbus, $title, $icon);
+
+ $droam->{gui}{w}->show;
+
+ my @connection_types = qw(network::connection::wireless network::connection::cellular_card);
+ @{$droam->{all_connections}} = map { $_->get_connections(automatic_only => 1) } @connection_types;
+ my $connection = $o_interface && find { $_->get_interface eq $o_interface } @{$droam->{all_connections}};
+ $connection ||= find { !$_->network_scan_is_slow } @{$droam->{all_connections}};
+ $droam->set_connection($connection) if $connection;
+ update_connections_list($droam);
+ update_on_connection_change($droam);
+
+ network::connection_manager::setup_dbus_handlers([ $droam ], $droam->{all_connections}, $droam->{on_network_event}, $dbus) if $dbus;
+
+ if ($o_ap && $droam->{connection}) {
+ $droam->{connection}{network} = $o_ap;
+ $droam->start_connection;
+ }
+
+ $droam->{gui}{w}->main;
+}
+
+1;
diff --git a/lib/network/drakvpn.pm b/lib/network/drakvpn.pm
new file mode 100644
index 0000000..c68127d
--- /dev/null
+++ b/lib/network/drakvpn.pm
@@ -0,0 +1,120 @@
+package network::drakvpn;
+
+=head1 NAME
+
+network::drakvpn - Interactive VPN configuration
+
+=head1 SYNOPSIS
+
+ use interactive;
+ use network::drakvpn;
+
+ my $in = 'interactive'->vnew('su');
+ network::drakvpn::create_connection($in);
+
+=cut
+
+use strict;
+use common;
+
+use network::vpn;
+
+sub create_connection {
+ my ($in) = @_;
+ my $vpn_type;
+ my $vpn_connection;
+ my $new_name;
+ require wizards;
+ my $wiz = wizards->new({
+ defaultimage => "drakvpn",
+ name => N("VPN configuration"),
+ pages => {
+ welcome => {
+ if_(!$::isInstall, no_back => 1),
+ name => N("Choose the VPN type"),
+ data => [ {
+ val => \$vpn_type, type => 'list',
+ list => [ sort { $a->get_description cmp $b->get_description } network::vpn::list_types ],
+ format => sub { $_[0] && $_[0]->get_description },
+ allow_empty_list => 1,
+ } ],
+ complete => sub {
+ $vpn_type or return 1;
+ my @packages = $vpn_type->get_packages;
+ if (@packages && !$in->do_pkgs->install(@packages)) {
+ $in->ask_warn(N("Error"), N("Could not install the packages (%s)!", join(', ', @packages)));
+ return 1;
+ }
+ if ($vpn_type->can('prepare')) {
+ my $wait = $in->wait_message(N("Please wait"), N("Initializing tools and detecting devices for %s...", $vpn_type->get_type));
+ if (!$vpn_type->prepare) {
+ undef $wait;
+ $in->ask_warn(N("Error"), N("Unable to initialize %s connection type!", $vpn_type->get_type));
+ return 1;
+ }
+ }
+ },
+ next => "vpn_name",
+ },
+ vpn_name => {
+ name => N("Please select an existing VPN connection or enter a new name."),
+ data => sub { [
+ { label => N("VPN connection"), val => \$vpn_connection, type => 'list',
+ list => [ $vpn_type->get_configured_connections, '' ],
+ format => sub { $_[0] ? $_[0]{name} : N("Configure a new connection...") },
+ gtk => { use_boxradio => 1 } },
+ { label => N("New name"), val => \$new_name, disabled => sub { $vpn_connection } },
+ ] },
+ complete => sub {
+ if (!$vpn_connection && !$new_name) {
+ $in->ask_warn(N("Warning"), N("You must select an existing connection or enter a new name."));
+ 1;
+ }
+ },
+ post => sub {
+ $vpn_connection ||= $vpn_type->new($new_name);
+ $vpn_connection->read_config;
+ $vpn_connection->can('get_key_settings') ? "vpn_key_settings" : "vpn_settings";
+ },
+ },
+ vpn_key_settings => {
+ name => N("Please enter the required key(s)"),
+ data => sub { $vpn_connection->get_key_settings },
+ next => "vpn_settings",
+ },
+ vpn_settings => {
+ name => N("Please enter the settings of your VPN connection"),
+ data => sub { $vpn_connection->get_settings },
+ post => sub {
+ $vpn_connection->write_config;
+ "connect";
+ },
+ },
+ connect => {
+ name => N("Do you want to start the connection now?"),
+ type => "yesorno",
+ post => sub {
+ my ($connect) = @_;
+ if ($connect) {
+ $vpn_connection->is_started and $vpn_connection->stop;
+ $vpn_connection->start($in) or $in->ask_warn(N("Warning"), N("Connection failed."));
+ }
+ require network::network;
+ network::network::reload_net_applet();
+ "end";
+ },
+ },
+ end => {
+ name => N("The VPN connection is now configured.
+
+This VPN connection can be automatically started together with a network connection.
+It can be done by reconfiguring the network connection and selecting this VPN connection.
+"),
+ end => 1,
+ },
+ },
+ });
+ $wiz->process($in);
+}
+
+1;
diff --git a/lib/network/ifw.pm b/lib/network/ifw.pm
new file mode 100644
index 0000000..1c7996d
--- /dev/null
+++ b/lib/network/ifw.pm
@@ -0,0 +1,160 @@
+package network::ifw;
+
+use Socket;
+use common;
+
+our @ISA = qw(dbus_object);
+
+sub init {
+ my ($bus, $filter) = @_;
+ my $con = $bus->{connection};
+ $con->add_filter($filter);
+ $con->add_match("type='signal',interface='com.mandriva.monitoring.ifw'");
+}
+
+sub new {
+ my ($type, $bus) = @_;
+ require dbus_object;
+ my $o = dbus_object::new($type,
+ $bus,
+ "com.mandriva.monitoring",
+ "/com/mandriva/monitoring/ifw",
+ "com.mandriva.monitoring.ifw");
+ $o;
+}
+
+sub set_blacklist_verdict {
+ my ($o, $seq, $blacklist) = @_;
+ $o->call_method('SetBlacklistVerdict', Net::DBus::dbus_uint32($seq), Net::DBus::dbus_uint32($blacklist));
+}
+
+sub unblacklist {
+ my ($o, $addr) = @_;
+ $o->call_method('UnBlacklist', Net::DBus::dbus_uint32($addr));
+}
+
+sub whitelist {
+ my ($o, $addr) = @_;
+ $o->call_method('Whitelist', Net::DBus::dbus_uint32($addr));
+}
+
+sub unwhitelist {
+ my ($o, $addr) = @_;
+ $o->call_method('UnWhitelist', Net::DBus::dbus_uint32($addr));
+}
+
+sub get_interactive {
+ my ($o) = @_;
+ $o->call_method('GetMode');
+}
+
+sub set_interactive {
+ my ($o, $mode) = @_;
+ $o->call_method('SetMode', Net::DBus::dbus_uint32($mode));
+}
+
+sub get_reports {
+ my ($o, $o_include_processed) = @_;
+ $o->call_method('GetReports', Net::DBus::dbus_uint32(to_bool($o_include_processed)));
+}
+
+sub get_blacklist {
+ my ($o) = @_;
+ $o->call_method('GetBlacklist');
+}
+
+sub get_whitelist {
+ my ($o) = @_;
+ $o->call_method('GetWhitelist');
+}
+
+sub clear_processed_reports {
+ my ($o) = @_;
+ $o->call_method('ClearProcessedReports');
+}
+
+sub send_alert_ack {
+ my ($o) = @_;
+ $o->call_method('SendAlertAck');
+}
+
+sub send_manage_request {
+ my ($o) = @_;
+ $o->call_method('SendManageRequest');
+}
+
+sub format_date {
+ my ($timestamp) = @_;
+ require c;
+ # "%c" has strange effects on utf-8 locales
+ #c::strftime("%c", localtime($timestamp));
+ c::strftime("%Y-%m-%d %H:%M:%S", localtime($timestamp));
+}
+
+sub get_service {
+ my ($port) = @_;
+ getservbyport($port, undef) || $port;
+}
+
+sub get_protocol {
+ my ($protocol) = @_;
+ getprotobynumber($protocol) || $protocol;
+}
+
+sub get_ip_address {
+ my ($addr) = @_;
+ inet_ntoa(pack('L', $addr));
+}
+
+sub resolve_address {
+ my ($ip_addr) = @_;
+ #- try to resolve address, timeout after 2 seconds
+ my $hostname;
+ eval {
+ local $SIG{ALRM} = sub { die "ALARM" };
+ alarm 2;
+ $hostname = gethostbyaddr(inet_aton($ip_addr), AF_INET);
+ alarm 0;
+ };
+ $hostname || $ip_addr;
+}
+
+sub attack_to_hash {
+ my ($args) = @_;
+ my $attack = { mapn { $_[0] => $_[1] } [ 'timestamp', 'indev', 'prefix', 'sensor', 'protocol', 'addr', 'port', 'icmp_type', 'seq', 'processed' ], $args };
+ $attack->{port} = unpack('S', pack('n', $attack->{port}));
+ $attack->{date} = format_date($attack->{timestamp});
+ $attack->{ip_addr} = get_ip_address($attack->{addr});
+ $attack->{hostname} = resolve_address($attack->{ip_addr});
+ $attack->{protocol} = get_protocol($attack->{protocol});
+ $attack->{service} = get_service($attack->{port});
+ $attack->{type} =
+ $attack->{prefix} eq 'SCAN' ? N("Port scanning")
+ : $attack->{prefix} eq 'SERV' ? N("Service attack")
+ : $attack->{prefix} eq 'PASS' ? N("Password cracking")
+ : $attack->{prefix} eq 'NEW' ? N("New connection")
+ : N(qq("%s" attack), $attack->{prefix});
+ $attack->{msg} =
+ $attack->{prefix} eq "SCAN" ? N("A port scanning attack has been attempted by %s.", $attack->{hostname})
+ : $attack->{prefix} eq "SERV" ? N("The %s service has been attacked by %s.", $attack->{service}, $attack->{hostname})
+ : $attack->{prefix} eq "PASS" ? N("A password cracking attack has been attempted by %s.", $attack->{hostname})
+ : $attack->{prefix} eq "NEW" ? N("%s is connecting on the %s service.", $attack->{hostname}, $attack->{service})
+ : N(qq(A "%s" attack has been attempted by %s), $attack->{prefix}, $attack->{hostname});
+ $attack;
+}
+
+sub parse_listen_message {
+ my ($args) = @_;
+ my $listen = { mapn { $_[0] => $_[1] } [ 'program', 'port' ], $args };
+ $listen->{port} = unpack('S', pack('n', $listen->{port}));
+ $listen->{service} = get_service($listen->{port});
+ $listen->{message} = N("The \"%s\" application is trying to make a service (%s) available to the network.",
+ $listen->{program},
+ $listen->{service} ne $listen->{port} ? $listen->{service} :
+ #-PO: this should be kept lowercase since the expression is meant to be used between brackets
+ N("port %d", $listen->{port}),
+ );
+ $listen;
+}
+
+1;
diff --git a/lib/network/invictus.pm b/lib/network/invictus.pm
new file mode 100644
index 0000000..91806d5
--- /dev/null
+++ b/lib/network/invictus.pm
@@ -0,0 +1,30 @@
+package network::invictus;
+
+use MDK::Common;
+
+my $ucarp_d = "/etc/ucarp.d";
+my $ct_sync_config = "/etc/sysconfig/ct_sync";
+
+sub read_config {
+ my ($invictus) = @_;
+ foreach (all($::prefix . $ucarp_d)) {
+ $invictus->{ucarp}{$_} = +{ getVarsFromSh($::prefix . $ucarp_d . '/' . $_) };
+ }
+ $invictus->{ct_sync} = +{ getVarsFromSh($::prefix . $ct_sync_config) };
+ $invictus->{ct_sync}{CMARKBIT} ||= 30;
+}
+
+sub write_config {
+ my ($invictus) = @_;
+ mkdir_p($::prefix . $ucarp_d);
+ foreach (keys %{$invictus->{ucarp}}) {
+ $invictus->{ucarp}{$_}{UPSCRIPT} ||= '/usr/share/invictus-firewall/ucarp-up.sh';
+ $invictus->{ucarp}{$_}{DOWNSCRIPT} ||= '/usr/share/invictus-firewall/ucarp-down.sh';
+ setVarsInShMode($::prefix . $ucarp_d . '/' . $_, 0600, $invictus->{ucarp}{$_},
+ qw(INTERFACE SRCIP VIRTIP VHID PASSWORD TAKEOVER UPSCRIPT DOWNSCRIPT));
+ }
+ setVarsInSh($::prefix . $ct_sync_config, $invictus->{ct_sync},
+ qw(ENABLE INTERFACE CMARKBIT));
+}
+
+1;
diff --git a/lib/network/ipsec.pm b/lib/network/ipsec.pm
new file mode 100644
index 0000000..846b07a
--- /dev/null
+++ b/lib/network/ipsec.pm
@@ -0,0 +1,619 @@
+package network::ipsec;
+
+
+
+use detect_devices;
+use run_program;
+use common;
+use log;
+
+#- debugg functions ----------
+sub recreate_ipsec_conf {
+ my ($ipsec) = @_;
+ foreach my $key1 (ikeys %$ipsec) {
+ if (! $ipsec->{$key1}{command}) {
+ print "$ipsec->{$key1}\n";
+ } else {
+ print $ipsec->{$key1}{command} . " " .
+ $ipsec->{$key1}{src_range} . " " .
+ $ipsec->{$key1}{dst_range} . " " .
+ $ipsec->{$key1}{upperspec} . " " .
+ $ipsec->{$key1}{flag} . " " .
+ $ipsec->{$key1}{direction} . " " .
+ $ipsec->{$key1}{ipsec} . "\n\t" .
+ $ipsec->{$key1}{protocol} . "/" .
+ $ipsec->{$key1}{mode} . "/" .
+ $ipsec->{$key1}{src_dest} . "/" .
+ $ipsec->{$key1}{level} . ";\n";
+ }
+ }
+}
+
+sub recreate_racoon_conf {
+ my ($racoon) = @_;
+ my $in_a_section = "n";
+ my $in_a_proposal_section = "n";
+ foreach my $key1 (ikeys %$racoon) {
+ if ($in_a_proposal_section eq "y") {
+ print "\t}\n}\n$racoon->{$key1}\n" if ! $racoon->{$key1}{1};
+ } elsif ($in_a_section eq "y") {
+ print "}\n$racoon->{$key1}\n" if ! $racoon->{$key1}{1};
+ } else {
+ print "$racoon->{$key1}\n" if ! $racoon->{$key1}{1};
+ }
+ $in_a_section = "n";
+ $in_a_proposal_section = "n";
+ foreach my $key2 (ikeys %{$racoon->{$key1}}) {
+ if ($racoon->{$key1}{$key2}[0] =~ /^path/) {
+ print "$racoon->{$key1}{$key2}[0] $racoon->{$key1}{$key2}[1] $racoon->{$key1}{$key2}[2];\n";
+ } elsif ($racoon->{$key1}{$key2}[0] =~ /^remote/) {
+ $in_a_section = "y";
+ $in_a_proposal_section = "n";
+ print "$racoon->{$key1}{$key2}[0] $racoon->{$key1}{$key2}[1] {\n";
+ } elsif ($racoon->{$key1}{$key2}[0] =~ /^sainfo/) {
+ $in_a_section = "y";
+ $in_a_proposal_section = "n";
+ if ($racoon->{$key1}{$key2}[2] && $racoon->{$key1}{$key2}[5]) {
+ print "$racoon->{$key1}{$key2}[0] $racoon->{$key1}{$key2}[1] $racoon->{$key1}{$key2}[2] $racoon->{$key1}{$key2}[3] $racoon->{$key1}{$key2}[4] $racoon->{$key1}{$key2}[5] $racoon->{$key1}{$key2}[6] {\n";
+ } else {
+ print "$racoon->{$key1}{$key2}[0] anonymous {\n";
+ }
+ } elsif ($racoon->{$key1}{$key2}[0] =~ /^proposal /) {
+ $in_a_proposal_section = "y";
+ print "\t$racoon->{$key1}{$key2}[0] {\n";
+ } elsif ($in_a_section eq "y" && $racoon->{$key1}{$key2}[0] =~ /^certificate_type/) {
+ print "\t$racoon->{$key1}{$key2}[0] $racoon->{$key1}{$key2}[1] $racoon->{$key1}{$key2}[2] $racoon->{$key1}{$key2}[3];\n";
+ } elsif ($in_a_section eq "y" && $racoon->{$key1}{$key2}[0] =~ /^#/) {
+ print "\t$racoon->{$key1}{$key2}[0] $racoon->{$key1}{$key2}[1]\n";
+ } elsif ($in_a_section eq "y") {
+ print "\t$racoon->{$key1}{$key2}[0] $racoon->{$key1}{$key2}[1];\n";
+ } elsif ($in_a_proposal_section eq "y" && $racoon->{$key1}{$key2}[0] =~ /^#/) {
+ print "\t\t$racoon->{$key1}{$key2}[0] $racoon->{$key1}{$key2}[1]\n";
+ } elsif ($in_a_proposal_section eq "y") {
+ print "\t\t$racoon->{$key1}{$key2}[0] $racoon->{$key1}{$key2}[1];\n";
+ }
+ }
+ }
+
+print "}\n";
+}
+
+sub recreate_ipsec_conf1_k24 {
+ my ($ipsec) = @_;
+ foreach my $key1 (ikeys %$ipsec) {
+ print "$key1-->$ipsec->{$key1}\n" if ! $ipsec->{$key1}{1};
+ foreach my $key2 (ikeys %{$ipsec->{$key1}}) {
+ if ($ipsec->{$key1}{$key2}[0] =~ m/^#/) {
+ print "\t$key2-->$ipsec->{$key1}{$key2}[0]\n";
+ } elsif ($ipsec->{$key1}{$key2}[0] =~ m/(conn|config|version)/) {
+ print "$key1-->$key2-->$ipsec->{$key1}{$key2}[0] $ipsec->{$key1}{$key2}[1]\n";
+ } else {
+ print "\t$key2-->$ipsec->{$key1}{$key2}[0]=$ipsec->{$key1}{$key2}[1]\n";
+ }
+ }
+ }
+}
+#- end of debug functions --------
+
+sub sys { system(@_) == 0 or log::l("[drakvpn] Warning, sys failed for $_[0]") }
+
+sub start_daemons () {
+ return if $::testing;
+ log::explanations("Starting daemons");
+ if (-e "/etc/rc.d/init.d/ipsec") {
+ system("/etc/rc.d/init.d/ipsec status >/dev/null") == 0 and sys("/etc/rc.d/init.d/ipsec stop");
+ sys("/etc/rc.d/init.d/$_ start >/dev/null"), sys("/sbin/chkconfig --level 345 $_ on") foreach 'ipsec';
+ } else {
+
+ }
+ sys("/etc/rc.d/init.d/$_ start >/dev/null"), sys("/sbin/chkconfig --level 345 $_ on") foreach 'shorewall';
+}
+
+sub stop_daemons () {
+ return if $::testing;
+ log::explanations("Stopping daemons");
+ if (-e "/etc/rc.d/init.d/ipsec") {
+ foreach (qw(ipsec)) {
+ system("/etc/rc.d/init.d/$_ status >/dev/null 2>/dev/null") == 0 and sys("/etc/rc.d/init.d/$_ stop");
+ }
+ sys("/sbin/chkconfig --level 345 $_ off") && -e "/etc/rc.d/init.d/$_" foreach 'ipsec';
+ }
+ system("/etc/rc.d/init.d/shorewall status >/dev/null 2>/dev/null") == 0 and sys("/etc/rc.d/init.d/shorewall stop >/dev/null");
+
+}
+
+sub set_config_file {
+ my ($file, @l) = @_;
+
+ my $done;
+ substInFile {
+ if (!$done && (/^#LAST LINE/ || eof)) {
+ $_ = join('', map { join("\t", @$_) . "\n" } @l) . $_;
+ $done = 1;
+ } else {
+ $_ = '' if /^[^#]/;
+ }
+ } "$::prefix/$file";
+}
+
+sub get_config_file {
+ my ($file) = @_;
+ map { [ split ' ' ] } grep { !/^#/ } cat_("$::prefix/$file");
+}
+
+
+#-------------------------------------------------------------------
+#---------------------- configure racoon_conf -----------------------
+#-------------------------------------------------------------------
+
+sub read_racoon_conf {
+ my ($racoon_conf) = @_;
+ my %conf;
+ my $nb = 0; #total number
+ my $i = 0; #nb within a section
+ my $in_a_section = "n";
+ my @line1;
+ my $line = "";
+ local $_;
+ open(my $LIST, "< $racoon_conf");
+ while (<$LIST>) {
+ chomp($_);
+ $line = $_;
+ $in_a_section = "n" if $line =~ /}/ && $line !~ /^#/;
+ $line =~ s/^\s+|\s*;|\s*{//g if $line !~ /^#/;
+ $line =~ /(.*)#(.*)/ if $line !~ /^#/; #- define before and after comment
+# print "--line-->$line\n";
+ my $data_part = $1;
+ my $comment_part = "#" . $2;
+ if ($data_part) {
+ $data_part =~ s/,//g;
+# print "@@".$data_part."->".$comment_part."\n";
+ @line1 = split /\s+/,$data_part;
+ @line1 = (@line1, $comment_part) if $comment_part;
+ } else {
+ @line1 = split /\s+/,$line;
+ }
+ if (!$line && $in_a_section eq "n") {
+ $nb++;
+ put_in_hash(\%conf, { $nb => $line });
+ $in_a_section = "n";
+ } elsif (!$line && $in_a_section eq "y") {
+ put_in_hash($conf{$nb} ||= {}, { $i => [ '' ] });
+ $i++;
+ } elsif ($line =~ /^path/) {
+ $i=1;
+ $nb++;
+ put_in_hash($conf{$nb} ||= {}, { $i => [@line1] });
+ $in_a_section = "n";
+ $i++;
+ } elsif ($line =~ /^#|^{|^}/) {
+ if ($in_a_section eq "y") {
+ put_in_hash($conf{$nb} ||= {}, { $i => [$line] });
+ $i++;
+ } else {
+ $nb++;
+ put_in_hash(\%conf, { $nb => $line });
+ $in_a_section = "n";
+ }
+ } elsif ($line =~ /^sainfo|^remote|^listen|^timer|^padding/ && $in_a_section eq "n") {
+ $i=1;
+ $nb++;
+ put_in_hash($conf{$nb} ||= {}, { $i => [@line1] });
+ $in_a_section = "y";
+ $i++;
+ } elsif ($line eq "proposal" && $in_a_section eq "y") {
+ $i=1;
+ $nb++;
+ put_in_hash($conf{$nb} ||= {}, { $i => [@line1] });
+ $in_a_section = "y";
+ $i++;
+ } else {
+ put_in_hash($conf{$nb} ||= {}, { $i => [@line1] });
+ $i++;
+ }
+ }
+
+\%conf;
+}
+
+sub display_racoon_conf {
+ my ($racoon) = @_;
+ my $display = "";
+ my $prefix_to_simple_line = "";
+ foreach my $key1 (ikeys %$racoon) {
+ if (!$racoon->{$key1}{1}) {
+ $display .= $prefix_to_simple_line . $racoon->{$key1} . "\n";
+ $prefix_to_simple_line = "";
+ } else {
+ foreach my $key2 (ikeys %{$racoon->{$key1}}) {
+ my $t = $racoon->{$key1}{1}[0];
+ my $f = $racoon->{$key1}{$key2}[0];
+ my $list_length = scalar @{$racoon->{$key1}{$key2}};
+ my $line = "";
+
+ if ($racoon->{$key1}{$key2}[0] eq "sainfo" && !$racoon->{$key1}{$key2}[2]) {
+ $line = "sainfo anonymous";
+ } else {
+ for (my $i = 0; $i <= $list_length-1; $i++) {
+
+ my $c = $racoon->{$key1}{$key2}[$i];
+ my $n = $racoon->{$key1}{$key2}[$i+1];
+
+ if ($c =~ /^path|^log|^timer|^listen|^padding|^remote|^proposal|^sainfo/) {
+ $line .= "$c ";
+ } elsif ($i == $list_length-2 && $n =~ /^#/) {
+ $line .= "$c; ";
+ } elsif ($i == $list_length-1) {
+ if ($f =~ /^#|^$|^timer|^listen|^padding|^remote|^proposal\s+|^sainfo/) {
+ $line .= $c;
+ } elsif ($c =~ /^#/) {
+ $line .= "\t$c";
+ } else {
+ $line .= "$c;";
+ }
+ } else {
+ $line .= "$c ";
+ }
+ }
+ }
+
+ if ($f =~ /^timer|^listen|^padding|^remote|^sainfo/) {
+ $line .= " {";
+ $prefix_to_simple_line = "";
+ } elsif ($f eq "proposal") {
+ $line = "\t" . $line . " {";
+ } elsif ($t eq "proposal") {
+ $line = "\t\t" . $line if $line ne "proposal";
+ $prefix_to_simple_line = "\t";
+ } else {
+ $line = "\t" . $line if $t !~ /^path|^log/;
+ $prefix_to_simple_line = "";
+ }
+ $display .= "$line\n";
+ }
+ }
+ }
+
+$display;
+
+}
+
+sub write_racoon_conf {
+ my ($racoon_conf, $racoon) = @_;
+ my $display = "";
+ my $prefix_to_simple_line = "";
+ foreach my $key1 (ikeys %$racoon) {
+ if (!$racoon->{$key1}{1}) {
+ $display .= $prefix_to_simple_line . $racoon->{$key1} . "\n";
+ $prefix_to_simple_line = "";
+ } else {
+ foreach my $key2 (ikeys %{$racoon->{$key1}}) {
+ my $t = $racoon->{$key1}{1}[0];
+ my $f = $racoon->{$key1}{$key2}[0];
+ my $list_length = scalar @{$racoon->{$key1}{$key2}};
+ my $line = "";
+
+ if ($racoon->{$key1}{$key2}[0] eq "sainfo" && !$racoon->{$key1}{$key2}[2]) {
+ $line = "sainfo anonymous";
+ } else {
+ for (my $i = 0; $i <= $list_length-1; $i++) {
+
+ my $c = $racoon->{$key1}{$key2}[$i];
+ my $n = $racoon->{$key1}{$key2}[$i+1];
+
+ if ($c =~ /^path|^log|^timer|^listen|^padding|^remote|^proposal|^sainfo/) {
+ $line .= "$c ";
+ } elsif ($i == $list_length-2 && $n =~ /^#/) {
+ $line .= "$c; ";
+ } elsif ($i == $list_length-1) {
+ if ($f =~ /^#|^$|^timer|^listen|^padding|^remote|^proposal\s+|^sainfo/) {
+ $line .= $c;
+ } elsif ($c =~ /^#/) {
+ $line .= "\t$c";
+ } else {
+ $line .= "$c;";
+ }
+ } else {
+ $line .= "$c ";
+ }
+ }
+ }
+
+ if ($f =~ /^timer|^listen|^padding|^remote|^sainfo/) {
+ $line .= " {";
+ $prefix_to_simple_line = "";
+ } elsif ($f eq "proposal") {
+ $line = "\t" . $line . " {";
+ } elsif ($t eq "proposal") {
+ $line = "\t\t" . $line if $line ne "proposal";
+ $prefix_to_simple_line = "\t";
+ } else {
+ $line = "\t" . $line if $t !~ /^path|^log/;
+ $prefix_to_simple_line = "";
+ }
+ $display .= "$line\n";
+ }
+ }
+ }
+
+open(my $ADD, "> $racoon_conf") or die "Can not open the $racoon_conf file for writing";
+ print $ADD "$display\n";
+
+}
+
+sub get_section_names_racoon_conf {
+ my ($racoon) = @_;
+ my @section_names;
+
+ foreach my $key1 (ikeys %$racoon) {
+ if (!$racoon->{$key1}{1}) {
+ next;
+ } else {
+ my $list_length = scalar @{$racoon->{$key1}{1}};
+ my $section_title = "";
+ my $separator = "";
+ for (my $i = 0; $i <= $list_length-1; $i++) {
+ my $s = $racoon->{$key1}{1}[$i];
+ if ($s !~ /^#|^proposal/) {
+ $section_title .= $separator . $s;
+ $separator = " ";
+ }
+ }
+ push(@section_names, $section_title) if $section_title ne "";
+ }
+ }
+
+ @section_names;
+
+}
+
+sub add_section_racoon_conf {
+ my ($new_section, $racoon) = @_;
+ put_in_hash($racoon, { max(keys %$racoon) + 1 => '' });
+ put_in_hash($racoon, { max(keys %$racoon) + 1 => $new_section });
+ put_in_hash($racoon, { max(keys %$racoon) + 1 => '}' }) if $new_section->{1}[0] !~ /^path|^remote/;
+ put_in_hash($racoon, { max(keys %$racoon) + 1 => '' }) if $new_section->{1}[0] =~ /^proposal/;
+ put_in_hash($racoon, { max(keys %$racoon) + 1 => '}' }) if $new_section->{1}[0] =~ /^proposal/;
+}
+
+sub matched_section_key_number_racoon_conf {
+ my ($section_name, $racoon) = @_;
+ foreach my $key1 (ikeys %$racoon) {
+ if (!$racoon->{$key1}{1}) {
+ next;
+ } else {
+ my $list_length = scalar @{$racoon->{$key1}{1}};
+ my $section_title = "";
+ my $separator = "";
+ for (my $i = 0; $i <= $list_length-1; $i++) {
+ my $s = $racoon->{$key1}{1}[$i];
+ if ($s !~ /^#|^proposal/) {
+ $section_title .= $separator . $s;
+ $separator = " ";
+ }
+ }
+ if ($section_title eq $section_name) {
+ return $key1;
+ }
+ }
+ }
+
+}
+
+sub already_existing_section_racoon_conf {
+ my ($section_name, $racoon, $racoon_conf) = @_;
+ if (-e $racoon_conf) {
+ foreach my $key1 (ikeys %$racoon) {
+ if (!$racoon->{$key1}{1}) {
+ next;
+ } elsif (find {
+ my $list_length = scalar @{$racoon->{$key1}{1}};
+ my $section_title = "";
+ my $separator = "";
+ for (my $i = 0; $i <= $list_length-1; $i++) {
+ my $s = $racoon->{$key1}{1}[$i];
+ if ($s !~ /^#|^proposal/) {
+ $section_title .= $separator . $s;
+ $separator = " ";
+ }
+ }
+
+ $section_title eq $section_name;
+
+ } ikeys %{$racoon->{$key1}}) {
+
+ return "already existing";
+ }
+ }
+ }
+
+}
+
+sub remove_section_racoon_conf {
+ my ($section_name, $racoon, $k) = @_;
+ if ($section_name =~ /^remote/) {
+
+ delete $racoon->{$k} if $k > 1 && !$racoon->{$k-1};
+ my $closing_curly_bracket = 0;
+ while ($closing_curly_bracket < 2) {
+ print "-->$k\n";
+ $closing_curly_bracket++ if $racoon->{$k} eq "}";
+ delete $racoon->{$k};
+ $k++;
+ }
+
+ } elsif ($section_name =~ /^path/) {
+
+ delete $racoon->{$k};
+ delete $racoon->{$k+1} if $racoon->{$k+1}{1} eq "";
+
+ } else {
+
+ delete $racoon->{$k};
+ delete $racoon->{$k+1} if $racoon->{$k+1}{1} eq "";
+ delete $racoon->{$k+2} if $racoon->{$k+2}{1} eq ""; #- remove assoc }
+
+ }
+
+}
+
+#-------------------------------------------------------------------
+#---------------------- configure ipsec_conf -----------------------
+#-------------------------------------------------------------------
+
+sub read_ipsec_conf {
+ my ($ipsec_conf) = @_;
+ my %conf;
+ my $nb = 0; #total number
+ my $i = 0; #nb within a connexion
+ my $in_a_conn = "n";
+ my $line = "";
+ my @line1;
+ local $_;
+ my @mylist;
+ my $myline = "";
+ open(my $LIST, "< $ipsec_conf"); #or die "Can not open the $ipsec_conf file for reading";
+ while (<$LIST>) {
+ chomp($_);
+ $myline = $_;
+ $myline =~ s/^\s+//;
+ $myline =~ s/;$//;
+ if ($myline =~ /^spdadd/) {
+ @mylist = split /\s+/,$myline;
+ $in_a_conn = "y";
+ $nb++;
+ next;
+ } elsif ($in_a_conn eq "y") {
+ @mylist = (@mylist, split '\s+|/',$myline);
+ put_in_hash(\%conf, { $nb => { command => $mylist[0],
+ src_range => $mylist[1],
+ dst_range => $mylist[2],
+ upperspec => $mylist[3],
+ flag => $mylist[4],
+ direction => $mylist[5],
+ ipsec => $mylist[6],
+ protocol => $mylist[7],
+ mode => $mylist[8],
+ src_dest => $mylist[9],
+ level => $mylist[10] } });
+ $in_a_conn = "n";
+ } else {
+ $nb++;
+ put_in_hash(\%conf, { $nb => $myline });
+ }
+ }
+
+ \%conf;
+}
+
+sub write_ipsec_conf {
+ my ($ipsec_conf, $ipsec) = @_;
+ my $display = "";
+ foreach my $key1 (ikeys %$ipsec) {
+ if (! $ipsec->{$key1}{command}) {
+ $display .= "$ipsec->{$key1}\n";
+ } else {
+ $display .= $ipsec->{$key1}{command} . " " .
+ $ipsec->{$key1}{src_range} . " " .
+ $ipsec->{$key1}{dst_range} . " " .
+ $ipsec->{$key1}{upperspec} . " " .
+ $ipsec->{$key1}{flag} . " " .
+ $ipsec->{$key1}{direction} . " " .
+ $ipsec->{$key1}{ipsec} . "\n\t" .
+ $ipsec->{$key1}{protocol} . "/" .
+ $ipsec->{$key1}{mode} . "/" .
+ $ipsec->{$key1}{src_dest} . "/" .
+ $ipsec->{$key1}{level} . ";\n";
+ }
+ }
+ open(my $ADD, "> $ipsec_conf") or die "Can not open the $ipsec_conf file for writing";
+ print $ADD $display;
+}
+
+sub display_ipsec_conf {
+ my ($ipsec) = @_;
+ my $display = "";
+
+ foreach my $key1 (ikeys %$ipsec) {
+ if (! $ipsec->{$key1}{command}) {
+ $display .= "$ipsec->{$key1}\n";
+ } else {
+ $display .= $ipsec->{$key1}{command} . " " .
+ $ipsec->{$key1}{src_range} . " " .
+ $ipsec->{$key1}{dst_range} . " " .
+ $ipsec->{$key1}{upperspec} . " " .
+ $ipsec->{$key1}{flag} . " " .
+ $ipsec->{$key1}{direction} . " " .
+ $ipsec->{$key1}{ipsec} . "\n\t" .
+ $ipsec->{$key1}{protocol} . "/" .
+ $ipsec->{$key1}{mode} . "/" .
+ $ipsec->{$key1}{src_dest} . "/" .
+ $ipsec->{$key1}{level} . ";\n";
+ }
+ }
+
+ $display;
+
+}
+
+sub get_section_names_ipsec_conf {
+ my ($ipsec) = @_;
+ my @section_names;
+
+ foreach my $key1 (ikeys %$ipsec) {
+ if ($ipsec->{$key1}{command} =~ m/(^spdadd)/) {
+ push(@section_names, "$ipsec->{$key1}{src_range} $ipsec->{$key1}{dst_range}");
+ }
+ }
+
+ @section_names;
+
+}
+
+sub remove_section_ipsec_conf {
+ my ($section_name, $ipsec) = @_;
+ foreach my $key1 (ikeys %$ipsec) {
+ if (find {
+ my $s = "$ipsec->{$key1}{src_range} $ipsec->{$key1}{dst_range}";
+ $s !~ /^#/ && $ipsec->{$key1}{src_range} && $section_name eq $s;
+ } ikeys %{$ipsec->{$key1}}) {
+ delete $ipsec->{$key1-1};
+ delete $ipsec->{$key1};
+ }
+ }
+}
+
+sub add_section_ipsec_conf {
+ my ($new_section, $ipsec) = @_;
+ put_in_hash($ipsec, { max(keys %$ipsec) + 1 => '' });
+ put_in_hash($ipsec, { max(keys %$ipsec) + 1 => $new_section });
+}
+
+sub already_existing_section_ipsec_conf {
+ my ($section_name, $ipsec) = @_;
+ foreach my $key1 (ikeys %$ipsec) {
+ if (find {
+ my $s = "$ipsec->{$key1}{src_range} $ipsec->{$key1}{dst_range}";
+ $s !~ /^#/ && $ipsec->{$key1}{src_range} &&
+ $section_name eq $s;
+ } ikeys %{$ipsec->{$key1}}) {
+ return "already existing";
+ }
+ }
+ return "no";
+}
+
+#- returns the hash key number of $section_name
+sub matched_section_key_number_ipsec_conf {
+ my ($section_name, $ipsec) = @_;
+ foreach my $key1 (ikeys %$ipsec) {
+ if (find {
+ my $s = "$ipsec->{$key1}{src_range} $ipsec->{$key1}{dst_range}";
+ $s !~ /^#/ && $ipsec->{$key1}{src_range} &&
+ $section_name eq $s;
+ } ikeys %{$ipsec->{$key1}}) {
+ return $key1;
+ }
+ }
+}
+1
diff --git a/lib/network/modem.pm b/lib/network/modem.pm
new file mode 100644
index 0000000..6c8fba0
--- /dev/null
+++ b/lib/network/modem.pm
@@ -0,0 +1,218 @@
+package network::modem; # $Id$
+
+use strict;
+use common;
+use any;
+use modules;
+use detect_devices;
+use network::network;
+use network::tools;
+
+sub get_user_home() {
+ my $home;
+ if ($ENV{USER} ne "root") {
+ #- kdesu case
+ my $user = find { $_->[0] eq $ENV{USER} } list_passwd();
+ $home = $user->[7] if $user;
+ }
+ $home ||= $ENV{HOME}; #- consolehelper case
+ $home;
+}
+
+sub ppp_read_conf() {
+ my $modem = {};
+ my %l = getVarsFromSh(get_user_home() . "/.kde/share/config/kppprc");
+ add2hash(\%l, { getVarsFromSh("$::prefix/usr/share/config/kppprc") });
+ $l{Authentication} = 4 if $l{Authentication} !~ /\d/;
+ $modem->{$_} ||= $l{$_} foreach qw(Authentication Gateway IPAddr SubnetMask);
+ $modem->{connection} ||= $l{Name};
+ $modem->{domain} ||= $l{Domain};
+ ($modem->{dns1}, $modem->{dns2}) = split(',', $l{DNS});
+
+ foreach (cat_("/etc/sysconfig/network-scripts/chat-ppp0")) {
+ /.*ATDT([\d#*]*)/ and $modem->{phone} ||= $1;
+ }
+ foreach (cat_("/etc/sysconfig/network-scripts/ifcfg-ppp0")) {
+ /NAME=(['"]?)(.*)\1/ and $modem->{login} ||= $2;
+ /^METRIC=(.*)/ and $modem->{METRIC} = $1;
+ }
+ $modem->{login} ||= $l{Username};
+ $modem->{passwd} = network::tools::passwd_by_login($modem->{login});
+ $modem->{$_} ||= '' foreach qw(connection phone login passwd auth domain dns1 dns2);
+ $modem->{auto_gateway} ||= defined $modem->{Gateway} && $modem->{Gateway} ne '0.0.0.0' ? N("Manual") : N("Automatic");
+ $modem->{auto_ip} ||= defined $modem->{IPAddr} && $modem->{IPAddr} ne '0.0.0.0' ? N("Manual") : N("Automatic");
+ $modem->{auto_dns} ||= $modem->{dns1} || $modem->{dns2} ? N("Manual") : N("Automatic");
+ $modem->{device} ||= '/dev/modem';
+ $modem;
+}
+
+#-----modem conf
+sub ppp_configure {
+ my ($net, $in, $modem) = @_;
+ $in->do_pkgs->install('ppp') if !$::testing;
+ $in->do_pkgs->install('kppp') if !$::testing && $in->do_pkgs->is_installed('kdebase4-runtime');
+
+ if ($modem->{device} ne "/dev/modem") {
+ my $dev = $modem->{device};
+ $dev =~ s!^/dev/!!;
+ devices::symlink_now_and_register({ device => $dev }, 'modem');
+ }
+
+ my %toreplace = map { $_ => $modem->{$_} } qw(Authentication AutoName connection dns1 dns2 domain IPAddr login passwd phone SubnetMask);
+ $toreplace{phone} =~ s/[^\d#*]//g;
+ if ($modem->{auto_dns} ne N("Automatic")) {
+ $toreplace{dnsserver} = join ',', map { $modem->{$_} } "dns1", "dns2";
+ $toreplace{dnsserver} .= $toreplace{dnsserver} && ',';
+ }
+
+ #- using peerdns or dns1,dns2 avoid writing a /etc/resolv.conf file.
+ $toreplace{peerdns} = "yes";
+
+ $toreplace{connection} ||= 'DialupConnection';
+ $toreplace{domain} ||= 'localdomain';
+ $toreplace{papname} = $toreplace{login} if member($modem->{Authentication}, 1, 3, 4);
+
+ # handle static/dynamic settings:
+ if ($modem->{auto_ip} eq N("Automatic")) {
+ $toreplace{$_} = '0.0.0.0' foreach qw(IPAddr SubnetMask);
+ } else {
+ $toreplace{$_} = $modem->{$_} foreach qw(IPAddr SubnetMask);
+ }
+ $toreplace{Gateway} = $modem->{auto_gateway} eq N("Automatic") ? '0.0.0.0' : $modem->{Gateway};
+
+ $toreplace{METRIC} = defined($modem->{METRIC}) ? $modem->{METRIC} : network::tools::get_default_metric("modem");
+
+ $net->{ifcfg}{ppp0} = {
+ DEVICE => "ppp0",
+ ONBOOT => "no",
+ USERCTL => "no",
+ MODEMPORT => "/dev/modem",
+ LINESPEED => "115200",
+ PERSIST => "yes",
+ DEFABORT => "yes",
+ DEBUG => "yes",
+ INITSTRING => "ATZ",
+ DEFROUTE => "yes",
+ HARDFLOWCTL => "yes",
+ ESCAPECHARS => "no",
+ PPPOPTIONS => "",
+ PAPNAME => $toreplace{papname},
+ REMIP => "",
+ NETMASK => "",
+ IPADDR => "",
+ MRU => "",
+ MTU => "",
+ DISCONNECTTIMEOUT => "5",
+ RETRYTIMEOUT => "60",
+ BOOTPROTO => "none",
+ PEERDNS => $toreplace{peerdns},
+ METRIC => $toreplace{METRIC},
+ if_($modem->{auto_dns} ne N("Automatic"),
+ map { qq(DNS$_=$toreplace{"dns$_"}\n) } grep { $toreplace{"dns$_"} } 1..2),
+ };
+
+ #- build chat-ppp0.
+ my @chat = <<END;
+'ABORT' 'BUSY'
+'ABORT' 'ERROR'
+'ABORT' 'NO CARRIER'
+'ABORT' 'NO DIALTONE'
+'ABORT' 'Invalid Login'
+'ABORT' 'Login incorrect'
+'' 'ATZ'
+END
+ if ($modem->{special_command}) {
+ push @chat, <<END;
+'OK' '$modem->{special_command}'
+END
+ }
+ push @chat, <<END;
+'OK' 'ATDT$toreplace{phone}'
+'TIMEOUT' '120'
+'CONNECT' ''
+END
+ if (member($modem->{Authentication}, 0, 2)) {
+ push @chat, <<END;
+'ogin:--ogin:' '$toreplace{login}'
+'ord:' '$toreplace{passwd}'
+END
+ }
+ push @chat, <<END;
+'TIMEOUT' '5'
+'~--' ''
+END
+ my $chat_file = "$::prefix/etc/sysconfig/network-scripts/chat-ppp0";
+ output_with_perm($chat_file, 0600, @chat);
+
+ network::tools::write_secret_backend($toreplace{login}, $toreplace{passwd});
+
+ #- install kppprc file according to used configuration.
+ mkdir_p("$::prefix/usr/share/config");
+
+ $toreplace{$_->[0]} = $modem->{$_->[0]} || $_->[1] foreach [ 'Timeout', 60 ], [ 'UseLockFile', 1 ], [ 'Enter', 'CR' ], [ 'Volume', 0 ],
+ [ 'BusyWait', 0 ], [ 'FlowControl', 'CRTSCTS' ], [ 'Speed', 115200 ];
+ output($modem->{kppprc} || "$::prefix/usr/share/config/kppprc", common::to_utf8(<<END));
+# KDE Config File
+
+[Account0]
+ExDNSDisabled=0
+AutoName=$toreplace{AutoName}
+ScriptArguments=
+AccountingEnabled=0
+DialString=ATDT
+Phonenumber=$toreplace{phone}
+IPAddr=$toreplace{IPAddr}
+Domain=$toreplace{domain}
+Name=$toreplace{connection}
+VolumeAccountingEnabled=0
+pppdArguments=
+Password=$toreplace{passwd}
+BeforeDisconnect=
+Command=
+ScriptCommands=
+Authentication=$toreplace{Authentication}
+DNS=$toreplace{dnsserver}
+SubnetMask=$toreplace{SubnetMask}
+AccountingFile=
+DefaultRoute=1
+Username=$toreplace{login}
+Gateway=$toreplace{Gateway}
+StorePassword=1
+DisconnectCommand=
+
+[Modem]
+BusyWait=$toreplace{BusyWait}
+Enter=$toreplace{Enter}
+FlowControl=$toreplace{FlowControl}
+Volume=$toreplace{Volume}
+Timeout=$toreplace{Timeout}
+UseCDLine=0
+UseLockFile=$toreplace{UseLockFile}
+Device=/dev/modem
+Speed=$toreplace{Speed}
+
+[Graph]
+InBytes=0,0,255
+Text=0,0,0
+Background=255,255,255
+Enabled=true
+OutBytes=255,0,0
+
+[General]
+QuitOnDisconnect=0
+ShowLogWindow=0
+DisconnectOnXServerExit=1
+DefaultAccount=$toreplace{connection}
+iconifyOnConnect=1
+Hint_QuickHelp=0
+AutomaticRedial=0
+PPPDebug=0
+NumberOfAccounts=1
+ShowClock=1
+DockIntoPanel=0
+pppdTimeout=30
+END
+ network::network::proxy_configure($::o->{miscellaneous});
+}
+
+1;
diff --git a/lib/network/monitor.pm b/lib/network/monitor.pm
new file mode 100644
index 0000000..7e644b6
--- /dev/null
+++ b/lib/network/monitor.pm
@@ -0,0 +1,136 @@
+package network::monitor;
+
+use common;
+use dbus_object;
+
+our @ISA = qw(dbus_object);
+
+my $monitor_service = "com.mandriva.monitoring";
+my $monitor_path = "/com/mandriva/monitoring/wireless";
+my $monitor_interface = "com.mandriva.monitoring.wireless";
+
+sub new {
+ my ($type, $bus) = @_;
+ dbus_object::new($type, $bus, $monitor_service, $monitor_path, $monitor_interface);
+}
+
+sub list_wireless {
+ my ($monitor, $o_intf) = @_;
+ my ($results, $list, %networks);
+ my $has_roaming;
+ #- first try to use mandi
+ eval {
+ $results = $monitor->call_method('ScanResults');
+ $list = $monitor->call_method('ListNetworks');
+ $has_roaming = 1;
+ } if $monitor;
+ #- try wpa_cli if we're root
+ if (!$has_roaming && !$>) {
+ $results = `/usr/sbin/wpa_cli scan_results 2>/dev/null`;
+ $list = `/usr/sbin/wpa_cli list_networks 2>/dev/null`;
+ $_ =~ s/^Selected interface (.*)\n//g foreach $results, $list;
+ }
+ if ($results && $list) {
+ #- bssid / frequency / signal level / flags / ssid
+ while ($results =~ /^((?:[0-9a-f]{2}:){5}[0-9a-f]{2})\t(\d+)\t(\d+)\t(.*?)\t(.*)$/mg) {
+ my ($ap, $frequency, $signal_strength, $flags, $essid) = ($1, $2, $3, $4, $5);
+ $networks{$ap}{ap} ||= $ap;
+ #- wpa_supplicant may list the network two times, use ||=
+ $networks{$ap}{frequency} ||= $frequency;
+ $networks{$ap}{signal_strength} ||= $signal_strength;
+ my $adhoc = $flags =~ s/\[ibss\]//i;
+ $networks{$ap}{mode} ||= $adhoc ? "Ad-Hoc" : "Managed";
+ $networks{$ap}{flags} ||= $flags;
+ $networks{$ap}{essid} ||= $essid;
+ }
+ if (any { $_->{signal_strength} > 100 } values %networks) {
+ #- signal level is really too high in wpa_supplicant
+ #- this should be standardized at some point
+ $_->{signal_strength} = int($_->{signal_strength}/3.5)
+ foreach values %networks;
+ }
+
+ #- network id / ssid / bssid / flags
+ while ($list =~ /^(\d+)\t(.*?)\t(.*?)\t(.*)$/mg) {
+ foreach my $net (uniq(if_($networks{$3}, $networks{$3}), grep { $_->{essid} eq $2 } values(%networks))) {
+ $net->{ap} = $3 if $3 ne 'any';
+ $net->{id} = $1;
+ $net->{essid} ||= $2;
+ $net->{current} = to_bool($4 eq '[CURRENT]');
+ }
+ }
+ } else {
+ #- else use iwlist
+ require network::connection::wireless;
+ my ($current_essid, $current_ap) = network::connection::wireless::get_access_point($o_intf);
+ if ($o_intf && !$> && !`/sbin/ip link show $o_intf up`) {
+ system("/sbin/ip link set $o_intf up");
+ }
+ my @list = `/sbin/iwlist $o_intf scanning 2>/dev/null`;
+ my $net = {};
+ my $quality_match = qr/Quality[:=](\S*)/;
+ my $eval_quality = sub {
+ my ($qual) = @_;
+ $qual =~ s!/0+$!/255!; #- prism54 reports quality with division by zero
+ $qual =~ m!/! ? eval($qual)*100 : $qual;
+ };
+ my ($has_key, $has_wpa, $has_eap);
+ foreach (@list) {
+ if ((/^\s*$/ || /Cell/) && exists $net->{ap}) {
+ $net->{current} = to_bool($net->{ap} ? $net->{ap} eq $current_ap : $net->{essid} && $net->{essid} eq $current_essid);
+ $net->{flags} = $has_wpa ? '[WPA]' : $has_key ? '[WEP]' : '';
+ $net->{flags} .= '[EAP]' if $has_eap;
+ $networks{$net->{ap}} = $net;
+ $net = {};
+ $has_key = $has_wpa = $has_eap = undef;
+ }
+ /Address: (.*)/ and $net->{ap} = lc($1);
+ /ESSID:"(.*?)"/ and $net->{essid} = $1;
+ /Mode:(\S*)/ and $net->{mode} = $1;
+ $net->{mode} = 'Managed' if $net->{mode} eq 'Master';
+ $_ =~ $quality_match and $net->{signal_strength} = $eval_quality->($1);
+ m|Signal level[:=]([0-9]+/[0-9]+)| and $net->{signal_level} = $eval_quality->($1);
+ /key:(\S*)\s/ && $1 eq 'on' and $has_key = 1;
+ /Extra:wpa_ie=|IE:.*WPA/ and $has_wpa = 1;
+ /Authentication Suites \(\d+\) :.*\b802\.1x\b/ and $has_eap = 1;
+ }
+ my $incorrect_quality =
+ (every { $_->{signal_strength} == 100 } values %networks) &&
+ (any { $_->{signal_strength} != $_->{signal_level} } values %networks);
+ foreach (values %networks) {
+ my $level = delete $_->{signal_level};
+ $_->{signal_strength} ||= $level;
+ $_->{signal_strength} = $level if $incorrect_quality;
+ }
+ if ($current_ap && exists $networks{$current_ap}) {
+ foreach (`/sbin/iwconfig $o_intf 2>/dev/null`) {
+ my $quality = $_ =~ $quality_match && $eval_quality->($1);
+ $networks{$current_ap}{signal_strength} = $quality if $quality;
+ }
+ }
+ }
+
+ foreach (values %networks) {
+ $_->{hidden} = member($_->{essid}, '', '<hidden>');
+ $_->{essid} eq '<hidden>' and undef $_->{essid};
+ $_->{name} = $_->{essid} || "[$_->{ap}]";
+ }
+ (\%networks, $has_roaming);
+}
+
+sub select_network {
+ my ($o, $id) = @_;
+ my $method = 'SelectNetwork';
+ if ($o) {
+ $o->call_method($method, Net::DBus::dbus_uint32($id));
+ } else {
+ require run_program;
+ run_program::run("dbus-send", "--system", "--type=method_call",
+ "--dest=" . $monitor_service,
+ $monitor_path,
+ $monitor_interface . '.' . $method,
+ 'uint32:' . $id);
+ }
+}
+
+1;
diff --git a/lib/network/ndiswrapper.pm b/lib/network/ndiswrapper.pm
new file mode 100644
index 0000000..22af6d6
--- /dev/null
+++ b/lib/network/ndiswrapper.pm
@@ -0,0 +1,160 @@
+package network::ndiswrapper;
+
+use strict;
+use common;
+use modules;
+use detect_devices;
+
+#- using bsd_glob() since glob("/DONT_EXIST") return "/DONT_EXIST" instead of () (and we don't want this)
+use File::Glob ':glob';
+
+my $ndiswrapper_root = "/etc/ndiswrapper";
+
+sub installed_drivers() {
+ grep { -d $::prefix . "$ndiswrapper_root/$_" } all($::prefix . $ndiswrapper_root);
+}
+
+sub present_devices {
+ my ($driver) = @_;
+ my @supported_devices;
+ foreach (all($::prefix . "$ndiswrapper_root/$driver")) {
+ my ($ids) = /^([0-9A-F]{4}:[0-9A-F]{4})\.[0-9A-F]\.conf$/;
+ $ids and push @supported_devices, $ids;
+ }
+ grep { member(uc(sprintf("%04x:%04x", $_->{vendor}, $_->{id})), @supported_devices) } detect_devices::probeall();
+}
+
+sub get_devices {
+ my ($in, $driver) = @_;
+ my @devices = present_devices($driver);
+ @devices or $in->ask_warn(N("Error"), N("No device supporting the %s ndiswrapper driver is present!", $driver));
+ @devices;
+}
+
+sub ask_driver {
+ my ($in) = @_;
+ if (my $inf_file = $in->ask_fileW({ title => N("Please select the correct driver"), message => N("Please select the Windows driver description (.inf) file, or corresponding driver file (.dll or .o files). Note that only drivers up to Windows XP are supported."), directory => $::prefix . "/media" })) {
+ my $driver = basename(lc($inf_file));
+ $driver =~ s/\.inf$//;
+
+ #- first uninstall the driver if present, may solve issues if it is corrupted
+ require run_program;
+ -d $::prefix . "$ndiswrapper_root/$driver" and run_program::rooted($::prefix, 'ndiswrapper', '-e', $driver);
+
+ unless (run_program::rooted($::prefix, 'ndiswrapper', '-i', $inf_file)) {
+ $in->ask_warn(N("Error"), N("Unable to install the %s ndiswrapper driver!", $driver));
+ return undef;
+ }
+
+ return $driver;
+ }
+ undef;
+}
+
+sub find_matching_devices {
+ my ($device) = @_;
+ my $net_path = '/sys/class/net';
+ my @devices;
+
+ my $is_driver_listed = sub { my ($driver) = @_; any { member($driver, @{$_->{drivers}}) } @devices };
+
+ require network::connection::ethernet;
+ foreach my $interface (all($net_path)) {
+ if (network::connection::ethernet::device_matches_interface($device, $interface)) {
+ my $driver = network::connection::ethernet::interface_to_driver($interface);
+ push @devices, { interface => $interface, drivers => [ $driver ] } if $driver;
+ }
+ }
+
+ #- find drivers with no net interface
+ my $sysfs_driver = $device->{sysfs_device} && basename(readlink($device->{sysfs_device} . "/driver/module"));
+ if ($sysfs_driver) {
+ my @sysfs_drivers = $sysfs_driver;
+ if ($sysfs_drivers[0] eq 'ssb') {
+ push @sysfs_drivers, map { basename(readlink($_)) } bsd_glob($device->{sysfs_device} . "/ssb*/driver/module");
+ }
+ @sysfs_drivers = grep { !$is_driver_listed->($_) } @sysfs_drivers;
+ push @devices, { interface => undef, drivers => \@sysfs_drivers } if @sysfs_drivers;
+ }
+
+ #- add original driver
+ push @devices, { interface => undef, drivers => [ $device->{driver} ] }
+ if !$is_driver_listed->($device->{driver}) && any { $_ eq $device->{driver} } modules::loaded_modules();
+
+ @devices;
+}
+
+sub find_conflicting_devices {
+ my ($device) = @_;
+ grep { !member("ndiswrapper", @{$_->{drivers}}) } find_matching_devices($device);
+}
+
+sub find_interface {
+ my ($device) = @_;
+ my $dev = find { member("ndiswrapper", @{$_->{drivers}}) } find_matching_devices($device);
+ $dev->{interface};
+}
+
+sub setup_device {
+ my ($in, $device) = @_;
+
+ my @conflicts = find_conflicting_devices($device);
+ if (@conflicts) {
+ $in->ask_yesorno(N("Warning"), N("The selected device has already been configured with the %s driver.
+Do you really want to use a ndiswrapper driver?", $conflicts[0]->{drivers}[0])) or return;
+ #- stop old interfaces
+ network::tools::stop_interface($_->{interface}, 0) foreach grep { defined $_->{interface} } @conflicts;
+ #- unload old modules before trying to load ndiswrapper
+ #- (sorted according to /proc/modules to handle deps nicely)
+ my @drivers = intersection([ modules::loaded_modules() ], [ map { @{$_->{drivers}} } @conflicts ]);
+ eval { modules::unload($_) } foreach @drivers;
+ }
+
+ #- unload ndiswrapper first so that the newly installed .inf files will be read
+ eval { modules::unload("ndiswrapper") };
+ eval { modules::load("ndiswrapper") };
+
+ if ($@) {
+ $in->ask_warn(N("Error"), N("Unable to load the ndiswrapper module!"));
+ return;
+ }
+
+ my $interface = find_interface($device);
+ unless ($interface) {
+ $in->ask_warn(N("Error"), N("Unable to find the ndiswrapper interface!"));
+ return;
+ }
+
+ $interface;
+}
+
+sub select_device {
+ my ($in) = @_;
+ my $driver;
+ my @drivers = installed_drivers();
+ if (@drivers) {
+ $driver ||= first(@drivers);
+ $in->ask_from('', N("Choose an ndiswrapper driver"), [
+ { type => "list", val => \$driver, allow_empty_list => 1,
+ list => [ undef, @drivers ],
+ format => sub { defined $_[0] ? N("Use the ndiswrapper driver %s", $_[0]) : N("Install a new driver") } }
+ ]) or return;
+ }
+ $driver ||= ask_driver($in) or return;
+
+ my @devices = get_devices($in, $driver) or return;
+ my $device;
+ if (@devices == 1) {
+ #- only one device matches installed driver
+ $device = $devices[0];
+ } else {
+ $in->ask_from('', N("Select a device:"), [
+ { type => "list", val => \$device, allow_empty_list => 1,
+ list => [ present_devices($driver) ],
+ format => sub { $_[0]{description} } }
+ ]) or return;
+ }
+ return $device;
+}
+
+1;
diff --git a/lib/network/net_applet/ifw.pm b/lib/network/net_applet/ifw.pm
new file mode 100644
index 0000000..22fc432
--- /dev/null
+++ b/lib/network/net_applet/ifw.pm
@@ -0,0 +1,227 @@
+package network::net_applet::ifw;
+
+use common;
+use network::ifw;
+use ugtk2 qw(:create :helpers :wrappers :dialogs);
+use mygtk2 qw(gtknew gtkset);
+
+sub init() {
+ network::ifw::init($network::net_applet::dbus, sub {
+ my ($_con, $msg) = @_;
+ my $member = $msg->get_member;
+ if ($member eq 'Attack') {
+ handle_ifw_message($msg->get_args_list);
+ } elsif ($member eq 'Listen') {
+ handle_ifw_listen($msg->get_args_list);
+ } elsif ($member eq 'Init') {
+ create();
+ } elsif ($member eq 'AlertAck') {
+ $network::net_applet::ifw_alert = 0;
+ }
+ });
+ create();
+}
+
+sub create() {
+ if ($network::net_applet::ifw) {
+ $network::net_applet::ifw->attach_object;
+ main::checkNetworkForce();
+ } else {
+ $network::net_applet::ifw = eval { network::ifw->new($network::net_applet::dbus) };
+ }
+}
+
+sub enable_ifw_alert() {
+ unless ($network::net_applet::ifw_alert) {
+ $network::net_applet::ifw_alert = 1;
+ network::net_applet::update_tray_icon();
+ Glib::Timeout->add(1000, sub {
+ network::net_applet::update_tray_icon();
+ $network::net_applet::ifw_alert;
+ });
+ }
+}
+
+sub disable_ifw_alert() {
+ eval { $network::net_applet::ifw->send_alert_ack };
+ $network::net_applet::ifw_alert = 0;
+ network::net_applet::update_tray_icon();
+}
+
+sub get_unprocessed_ifw_messages() {
+ my @packets = eval { $network::net_applet::ifw->get_reports };
+ while (my @ifw_message = splice(@packets, 0, 10)) {
+ handle_ifw_message(@ifw_message);
+ }
+}
+
+sub set_verdict {
+ my ($attack, $apply_verdict) = @_;
+ eval { $apply_verdict->($attack) };
+ $@ and err_dialog(N("Interactive Firewall"), N("Unable to contact daemon"));
+}
+
+sub apply_verdict_blacklist {
+ my ($attack) = @_;
+ $network::net_applet::ifw->set_blacklist_verdict($attack->{seq}, 1);
+}
+
+sub apply_verdict_ignore {
+ my ($attack) = @_;
+ $network::net_applet::ifw->set_blacklist_verdict($attack->{seq}, 0);
+}
+
+sub apply_verdict_whitelist {
+ my ($attack) = @_;
+ $network::net_applet::ifw->whitelist($attack->{addr});
+ apply_verdict_ignore($attack);
+}
+
+sub handle_ifw_message {
+ my $message = network::ifw::attack_to_hash(\@_);
+ unless ($message->{msg}) {
+ print "unhandled attack type, skipping\n";
+ return;
+ }
+ my $is_attack = $message->{prefix} ne 'NEW';
+ enable_ifw_alert() if $is_attack;
+ $network::net_applet::notification_queue->add({
+ title => N("Interactive Firewall"),
+ pixbuf => $network::net_applet::pixbufs{firewall},
+ message => $message->{msg},
+ timeout => sub {
+ set_verdict($message, \&apply_verdict_ignore);
+ },
+ if_($is_attack,
+ urgency => 'critical',
+ actions => [ {
+ action => 'clicked',
+ label => #-PO: "Process" is a verb
+ N("Process attack"),
+ callback => sub {
+ disable_ifw_alert();
+ ask_attack_verdict($message);
+ },
+ } ],
+ ),
+ });
+}
+
+sub ask_attack_verdict {
+ my ($attack) = @_;
+
+ my $w = ugtk2->new(N("Interactive Firewall: intrusion detected"),
+ icon => "drakfirewall");
+ my ($blacklist, $whitelist, $ignore, $auto);
+
+ my $update_automatic_mode = sub { $auto->get_active and $network::net_applet::interactive_cb->set_active(1) };
+ my $set_verdict = sub {
+ my ($verdict) = @_;
+ set_verdict($attack, $verdict);
+ $network::net_applet::notification_queue->process_next;
+ };
+ gtkadd($w->{window},
+ gtknew('VBox', spacing => 5, children_loose => [
+ gtknew('HBox', children => [
+ 0, Gtk2::Image->new_from_stock('gtk-dialog-warning', 'dialog'),
+ 0, gtknew('Label', text => " "),
+ 1, gtknew('VBox', children => [
+ 0, $attack->{msg},
+ 0, N("What do you want to do with this attacker?")
+ ])
+ ]),
+ gtksignal_connect(gtkadd(Gtk2::Expander->new(N("Attack details")),
+ gtknew('HBox', children => [
+ 0, gtknew('Label', text => " "),
+ 1, gtknew('VBox', children_loose => [
+ N("Attack time: %s", $attack->{date}),
+ N("Network interface: %s", $attack->{indev}),
+ N("Attack type: %s", $attack->{prefix}),
+ if_($attack->{protocol}, N("Protocol: %s", $attack->{protocol})),
+ N("Attacker IP address: %s", $attack->{ip_addr}),
+ if_($attack->{hostname} ne $attack->{ip_addr}, N("Attacker hostname: %s", $attack->{hostname})),
+ (
+ $attack->{service} ne $attack->{port} ?
+ N("Service attacked: %s", $attack->{service}) :
+ N("Port attacked: %s", $attack->{port}),
+ ),
+ if_($attack->{icmp_type}, N("Type of ICMP attack: %s", $attack->{icmp_type}))
+ ]),
+ ])),
+ activate => sub { $_[0]->get_expanded and $w->shrink_topwindow }
+ ),
+ $auto = gtknew('CheckButton', text => N("Always blacklist (do not ask again)"), toggled => sub {
+ $whitelist->set_sensitive(!$_[0]->get_active);
+ $ignore->set_sensitive(!$_[0]->get_active);
+ }),
+ gtknew('HButtonBox', layout => 'edge', children_loose => [
+ $blacklist = gtknew('Button', text => N("Blacklist"), clicked => sub {
+ $w->destroy;
+ $update_automatic_mode->();
+ $set_verdict->(\&apply_verdict_blacklist);
+ }),
+ $whitelist = gtknew('Button', text => N("Whitelist"), clicked => sub {
+ $w->destroy;
+ $update_automatic_mode->();
+ $set_verdict->(\&apply_verdict_whitelist);
+ }),
+ $ignore = gtknew('Button', text => N("Ignore"), clicked => sub {
+ $w->destroy;
+ $set_verdict->(\&apply_verdict_ignore);
+ }),
+ ]),
+ ]));
+ eval { $auto->set_active(!$network::net_applet::ifw->get_interactive) };
+ $blacklist->grab_focus;
+ gtksignal_connect($w->{window}, delete_event => sub {
+ $set_verdict->(\&apply_verdict_ignore);
+ });
+ $w->{window}->show_all;
+}
+
+sub handle_ifw_listen {
+ my $listen = network::ifw::parse_listen_message(\@_);
+ enable_ifw_alert();
+ $network::net_applet::notification_queue->add({
+ title => N("Interactive Firewall: new service"),
+ pixbuf => $network::net_applet::pixbufs{firewall},
+ message => $listen->{message},
+ actions => [ {
+ action => 'clicked',
+ label => #-PO: "Process" is a verb
+ N("Process connection"),
+ callback => sub {
+ disable_ifw_alert();
+ ask_listen_verdict($listen);
+ },
+ } ],
+ });
+}
+
+sub ask_listen_verdict {
+ my ($listen) = @_;
+
+ my $w = ugtk2->new(N("Interactive Firewall: new service"), icon => "drakfirewall");
+ my $set_verdict = sub {
+ $network::net_applet::notification_queue->process_next;
+ };
+ gtkadd($w->{window},
+ gtknew('VBox', spacing => 5, children_loose => [
+ gtknew('HBox', children => [
+ 0, Gtk2::Image->new_from_stock('gtk-dialog-warning', 'dialog'),
+ 1, gtknew('VBox', children => [
+ 0, $listen->{message},
+ 0, N("Do you want to open this service?"),
+ ])
+ ]),
+ gtknew('CheckButton', text => N("Remember this answer"), toggled => sub {}),
+ gtknew('HButtonBox', layout => 'edge', children_loose => [
+ gtknew('Button', text => N("Allow"), clicked => sub { $w->destroy; $set_verdict->(1) }),
+ gtknew('Button', text => N("Block"), clicked => sub { $w->destroy; $set_verdict->(0) }),
+ ]),
+ ]));
+ gtksignal_connect($w->{window}, delete_event => sub { $set_verdict->() });
+ $w->{window}->show_all;
+}
+
+1;
diff --git a/lib/network/netcenter.pm b/lib/network/netcenter.pm
new file mode 100755
index 0000000..29e2232
--- /dev/null
+++ b/lib/network/netcenter.pm
@@ -0,0 +1,215 @@
+#!/usr/bin/perl
+# Olivier Blin, 2007 <oblin@mandriva.com>
+# Licensed under the GPL
+
+package network::netcenter;
+
+use strict;
+use common;
+use mygtk2;
+use ugtk2 qw(:create :helpers :wrappers);
+use network::connection;
+use network::connection_manager;
+use network::tools;
+use network::network;
+use run_program;
+
+sub build_cmanager {
+ my ($in, $net, $w, $pixbufs, $connection) = @_;
+
+ my $cmanager = network::connection_manager->new($in, $net, $w, $pixbufs);
+ $cmanager->set_connection($connection);
+ $cmanager->{gui}{show_unique_network} = $cmanager->{connection}->has_unique_network;
+
+ if ($connection->can('get_networks')) {
+ $cmanager->create_networks_list;
+ #- do not check if it is slow (either scan or device check) or unavailable
+ $cmanager->update_networks
+ if !$connection->network_scan_is_slow && $cmanager->check_setup;
+ }
+ $cmanager;
+}
+
+sub build_cmanager_box {
+ my ($cmanager, $is_first) = @_;
+
+ my $head = gtknew('HBox', children => [
+ 0, $cmanager->{gui}{status_image} = gtknew('Image'),
+ 0, gtknew('Label', padding => [ 5, 0 ]),
+ 1, gtknew('VBox', children_tight => [
+ gtknew('HBox', children => [
+ 1, gtknew('Label', alignment => [ 0, 0 ], text_markup => '<b>' . $cmanager->{connection}->get_type_description . '</b>'),
+ 0, gtknew('Label', padding => [ 2, 0 ]),
+ 0, $cmanager->{gui}{labels}{interface} = gtknew('Label', alignment => [ 0, 0 ], text_markup => $cmanager->{connection}->get_interface ? '<b>' . $cmanager->{connection}->get_interface . '</b>' : ""),
+ ]),
+ gtknew('Label', ellipsize => 'end', alignment => [ 0, 0 ], text_markup => $cmanager->{connection}->get_description),
+ ]),
+ ]);
+ my $content = gtknew('HBox', children => [
+ 0, gtknew('Label', padding => [ 5, 0 ]),
+ 1, gtknew('VBox', spacing => 5, children_tight => [
+ ($cmanager->{connection}->can('get_networks') ? (
+ $cmanager->{gui}{show_unique_network} ? (
+ $cmanager->{gui}{networks_list},
+ ): (
+ gtknew('Label', text => N("Please select your network:"), alignment => [ 0, 0 ]),
+ gtknew('ScrolledWindow', height => 160, child => $cmanager->{gui}{networks_list})
+ ),
+ ) : ()),
+ gtknew('HBox', children => [
+ 1, gtknew('HButtonBox', spacing => 6, layout => 'start', children_loose => [
+ $cmanager->{gui}{buttons}{monitor} =
+ gtknew('Button', text => N("_: This is a verb\nMonitor"),
+ image => gtknew('Image', file => 'monitor-16'),
+ clicked => sub { $cmanager->monitor_connection }),
+ $cmanager->{gui}{buttons}{configure} =
+ gtknew('Button', text => N("Configure"),
+ image => gtknew('Image', file => 'configure-16'),
+ clicked => sub { $cmanager->configure_connection }),
+ ($cmanager->{connection}->can('get_networks') ?
+ ($cmanager->{gui}{buttons}{refresh} =
+ gtknew('Button', text => N("Refresh"),
+ image => gtknew('Image', file => 'refresh', size => 16),
+ clicked => sub { $cmanager->update_networks }))
+ : ()),
+ ]),
+ 0, $cmanager->{gui}{buttons}{connect_toggle} =
+ gtknew('Button',
+ image => gtknew('Image', file => 'activate-16'),
+ clicked => sub { $cmanager->toggle_connection }),
+ ]),
+ ]),
+ ]);
+
+ my $expander = gtknew('Expander');
+ my $on_expand = sub {
+ my ($expanded) = @_;
+ if ($expanded && $cmanager->{connection}->can('get_networks') &&
+ !$cmanager->{connection}{probed_networks} && $expanded) {
+ gtkflush();
+ $cmanager->update_networks;
+ }
+ };
+ my $toggle_expand = sub {
+ my $was_expanded = $expander->get_expanded;
+ $was_expanded ? $content->hide : $content->show_all;
+ $on_expand->(!$was_expanded);
+ };
+ $expander->signal_connect(activate => $toggle_expand);
+ my $eventbox = gtksignal_connect(Gtk2::EventBox->new, button_press_event => sub {
+ $_[1]->button == 1 or return;
+ $toggle_expand->();
+ my $was_expanded = $expander->get_expanded;
+ $expander->set_expanded(!$was_expanded);
+ });
+ my $box = gtknew('VBox', spacing => 5, children_tight => [
+ (!$is_first ? Gtk2::HSeparator->new : ()),
+ gtknew('HBox', children => [
+ 0, $expander,
+ 1, gtkadd($eventbox, $head),
+ ]),
+ $content,
+ ]);
+ $content->hide;
+
+ $cmanager->update_on_status_change;
+
+ $cmanager->{parent_box} = $box;
+}
+
+sub get_connections() {
+ my @all_connections = map { $_->get_connections(automatic_only => 1, fast_only => 1) } network::connection::get_types;
+ @all_connections = grep { !network::tools::is_zeroconf_interface($_->get_interface) } @all_connections;
+ my ($sysfs, $no_sysfs) = partition { exists $_->{device}{sysfs_device} } @all_connections;
+ my ($real, $other) = partition { network::tools::is_real_interface($_->get_interface) } @$sysfs;
+ (
+ (uniq_ { $_->{device}{sysfs_device} } @$real),
+ (uniq_ { $_->{device}{sysfs_device} } @$other),
+ (uniq_ { $_->{device}{interface} } @$no_sysfs),
+ );
+}
+
+sub advanced_settings {
+ my ($in, $net) = @_;
+ my $u = network::network::advanced_settings_read();
+ my $old_crda = $net->{network}{CRDA_DOMAIN};
+ if (network::network::advanced_choose($in, $net, $u)) {
+ network::network::advanced_settings_write($u);
+ # check if the CRDA changed
+ if ($old_crda ne $net->{network}{CRDA_DOMAIN}) {
+ # reconfiguring wireless domain
+ run_program::run("iw", "reg", "set", $net->{network}{CRDA_DOMAIN});
+ }
+ network::network::write_network_conf($net);
+ }
+}
+
+sub main {
+ my ($in, $net, $dbus) = @_;
+
+ my $wait = $in->wait_message(N("Please wait"), N("Please wait"));
+
+ my $title = N("Network Center");
+ my $icon = '/usr/share/mcc/themes/default/drakroam-mdk.png';
+
+ $ugtk2::wm_icon = $icon;
+ my $w = ugtk2->new($title);
+ #- so that transient_for is defined, for wait messages and popups to be centered
+ $::main_window = $w->{real_window};
+
+ my @connections = get_connections();
+
+ my $pixbufs = network::connection_manager::create_pixbufs();
+ my @cmanagers = map { build_cmanager($in, $net, $w, $pixbufs, $_) } @connections;
+
+ (undef, my $rootwin_height) = gtkroot()->get_size;
+ my $scrolled_height = $rootwin_height > 480 ? 400 : 295;
+ my $managers_box;
+ gtkadd($w->{window},
+ gtknew('VBox', spacing => 5, children => [
+ $::isEmbedded ? () : (0, Gtk2::Banner->new($icon, $title)),
+ if_($net->{PROFILE} && network::network::netprofile_count() > 0, 0, gtknew('Label', text_markup => N("You are currently using the network profile <b>%s</b>", $net->{PROFILE})) ),
+ 1, gtknew('ScrolledWindow', width => 600, height => $scrolled_height, shadow_type => 'none',
+ child => $managers_box = gtknew('VBox', spacing => 5, children_tight => [
+ map_index { build_cmanager_box($_, $::i == 0) } @cmanagers,
+ ])),
+ 0, gtknew('HButtonBox', spacing => 6, layout => 'end', children_loose => [
+ gtknew('Button', text => N("Advanced settings"), clicked => sub { advanced_settings($in, $net) }),
+ gtknew('Button', text => N("Quit"), clicked => sub { Gtk2->main_quit }),
+ ]),
+ ]),
+ );
+
+ if ($dbus) {
+ $dbus->{connection}->add_filter(sub {
+ my ($_con, $msg) = @_;
+ if ($msg->get_interface eq 'com.mandriva.network' && $msg->get_member eq 'status') {
+ my ($status, $interface) = $msg->get_args_list;
+ my $cmanager = find { $_->{connection}->get_interface eq $interface } @cmanagers;
+ if ($status eq "add") {
+ if (!$cmanager) {
+ detect_devices::probeall_update_cache();
+ my $connection = find { $_->get_interface eq $interface } get_connections()
+ or return;
+ $cmanager = build_cmanager($in, $net, $w, $pixbufs, $connection);
+ push @connections, $connection;
+ push @cmanagers, $cmanager;
+ my $box = build_cmanager_box($cmanager, @connections == 0);
+ $managers_box ->add($box);
+ $box->show_all;
+ }
+ $cmanager->{parent_box}->show;
+ }
+ if ($status eq "remove") {
+ $cmanager->{parent_box}->hide if $cmanager;
+ }
+ }
+ });
+ network::connection_manager::setup_dbus_handlers(\@cmanagers, \@connections, undef, $dbus);
+ }
+
+ undef $wait;
+ $w->main;
+}
+
+1;
diff --git a/lib/network/netconnect.pm b/lib/network/netconnect.pm
new file mode 100644
index 0000000..1f6cbc1
--- /dev/null
+++ b/lib/network/netconnect.pm
@@ -0,0 +1,867 @@
+package network::netconnect; # $Id$
+
+use strict;
+use common;
+use log;
+use detect_devices;
+use list_modules;
+use modules;
+use mouse;
+use services;
+use network::network;
+use network::tools;
+use network::thirdparty;
+use network::connection;
+
+sub detect {
+ my ($modules_conf, $auto_detect, $o_class) = @_;
+ my %l = (
+ isdn => sub {
+ require network::connection::isdn;
+ $auto_detect->{isdn} = network::connection::isdn::detect_backend($modules_conf);
+ },
+ modem => sub {
+ $auto_detect->{modem} = { map { $_->{description} || "$_->{MANUFACTURER}|$_->{DESCRIPTION} ($_->{device})" => $_ } detect_devices::getModem($modules_conf) };
+ },
+ );
+ $l{$_}->() foreach $o_class || keys %l;
+ return;
+}
+
+sub detect_timezone() {
+ my %tmz2country = (
+ 'Europe/Paris' => N("France"),
+ 'Europe/Amsterdam' => N("Netherlands"),
+ 'Europe/Rome' => N("Italy"),
+ 'Europe/Brussels' => N("Belgium"),
+ 'America/New_York' => N("United States"),
+ 'Europe/London' => N("United Kingdom")
+ );
+ my %tm_parse = MDK::Common::System::getVarsFromSh("$::prefix/etc/sysconfig/clock");
+ my @country;
+ foreach (keys %tmz2country) {
+ if ($_ eq $tm_parse{ZONE}) {
+ unshift @country, $tmz2country{$_};
+ } else { push @country, $tmz2country{$_} }
+ }
+ \@country;
+}
+
+sub real_main {
+ my ($net, $in, $modules_conf) = @_;
+ #- network configuration should have been already read in $net at this point
+ my $mouse = $::o->{mouse} || {};
+ my (@connections_list, $connection, $provider_settings, $protocol_settings, $access_settings, $control_settings);
+ my $connection_compat;
+ my ($hardware_settings, $network_access_settings, $address_settings, $hostname_settings);
+ my ($modem, $modem_name, $modem_dyn_dns, $modem_dyn_ip);
+ my ($up);
+ my ($isdn, $isdn_name, $isdn_type, %isdn_cards, @isdn_dial_methods);
+ my $my_isdn = join('', N("Manual choice"), " (", N("Internal ISDN card"), ")");
+ my $success = 1;
+ my $has_internet = 1;
+ my $db_path = "/usr/share/apps/kppp/Provider";
+ my (%countries, @isp, $country, $provider, $old_provider);
+
+ my $system_file = '/etc/sysconfig/drakx-net';
+ my %global_settings = getVarsFromSh($system_file);
+
+ my $_w = N("Protocol for the rest of the world");
+ my %isdn_protocols = (
+ 2 => N("European protocol (EDSS1)"),
+ 3 => N("Protocol for the rest of the world\nNo D-Channel (leased lines)"),
+ );
+
+ $net->{autodetect} = {};
+
+ my %ppp_auth_methods = (
+ 0 => N("Script-based"),
+ 1 => N("PAP"),
+ 2 => N("Terminal-based"),
+ 3 => N("CHAP"),
+ 4 => N("PAP/CHAP"),
+ );
+
+ my %steps_compat = (
+ 'network::connection::isdn' => 'isdn',
+ 'network::connection::pots' => 'modem',
+ );
+
+ my $get_next = sub {
+ my ($step) = @_;
+ my @steps = (
+ "select_connection" => sub { 0 },
+ "configure_hardware" => sub { $connection->can('get_hardware_settings') },
+ #- network is for example wireless/3G access point
+ "select_network" => sub { $connection->can('get_networks') },
+ "configure_network_access" => sub { $connection->can('get_network_access_settings') },
+ #- allow to select provider after network
+ "select_provider" => sub { $connection->can('get_providers') },
+ #- protocol may depend on provider settings (xDSL)
+ "select_protocol" => sub { $connection->can('get_protocols') },
+ #- peer settings may depend on provider and protocol (VPI/VCI for xDSL)
+ "configure_access" => sub { $connection->can('get_access_settings') },
+ "configure_address" => sub { ($connection->can('get_address_settings') || $connection->can('get_hostname_settings')) && !text2bool($global_settings{AUTOMATIC_ADDRESS}) },
+ "configure_control" => sub { $connection->can('get_control_settings') },
+ "apply_connection" => sub { 1 },
+ );
+ my $can;
+ foreach (group_by2(@steps)) {
+ $can && $_->[1]->() and return $_->[0];
+ $can ||= $_->[0] eq $step;
+ }
+ };
+
+ use locale;
+ set_l10n_sort();
+
+ require wizards;
+ my $wiz = wizards->new(
+ {
+ defaultimage => "drakconnect.png",
+ name => N("Network & Internet Configuration"),
+ pages => {
+ welcome => {
+ pre => sub { undef $net->{type} },
+ if_(!$::isInstall, no_back => 1),
+ name => N("Choose the connection you want to configure") . if_($net->{PROFILE} && network::network::netprofile_count() > 0, "\n".N("Those settings will be saved for the network profile <b>%s</b>", $net->{PROFILE}) ),
+ if_(!$::isInstall, interactive_help_id => 'configureNetwork'),
+ data => [ { list => [ network::connection::get_types ],
+ type => 'list', val => \$net->{type}, format => sub { $_[0] && $_[0]->get_type_description },
+ gtk => { use_scrolling => 1 } } ],
+ complete => sub {
+ my @packages = $net->{type}->can('get_packages') ? $net->{type}->get_packages : ();
+ if (@packages && !$in->do_pkgs->install(@packages)) {
+ $in->ask_warn(N("Error"), N("Could not install the packages (%s)!", join(', ', @packages)));
+ 1;
+ }
+ },
+ post => sub {
+ if (exists $steps_compat{$net->{type}}) {
+ return $steps_compat{$net->{type}};
+ }
+ @connections_list = $net->{type}->get_connections(automatic_only => text2bool($global_settings{AUTOMATIC_IFACE_CHOICE}));
+ @connections_list ? "select_connection" : "no_connection";
+ },
+ },
+
+ select_connection => {
+ name => sub { $net->{type}->get_type_name . "\n\n" . N("Select the network interface to configure:") },
+ data => [ { val => \$connection, type => 'list', list => \@connections_list,
+ format => sub { $_[0] && N("%s: %s", $_[0]->get_interface, $_[0]->get_description) }, allow_empty_list => !text2bool($global_settings{AUTOMATIC_IFACE_CHOICE})} ],
+ complete => sub {
+ $connection->setup_thirdparty($in) or return 1;
+ $connection->prepare_device;
+ if ($connection->can("check_device") && !$connection->check_device) {
+ $in->ask_warn('', $connection->{device}{error});
+ return 1;
+ }
+ return 0;
+ },
+ post => sub {
+ $connection->load_interface_settings;
+ $get_next->("select_connection");
+ },
+ },
+
+ no_connection => {
+ name => sub { $net->{type}->get_type_name . "\n\n" . N("No device can be found for this connection type.") },
+ end => 1,
+ },
+
+ configure_hardware => {
+ pre => sub {
+ $hardware_settings = $connection->get_hardware_settings;
+ $connection->guess_hardware_settings if $connection->can('guess_hardware_settings');
+ },
+ name => sub { $net->{type}->get_type_name . "\n\n" . N("Hardware Configuration") },
+ data => sub { $hardware_settings },
+ complete => sub {
+ if ($connection->can("check_hardware_settings") && !$connection->check_hardware_settings) {
+ $in->ask_warn('', $connection->{hardware}{error});
+ return 1;
+ }
+ return 0 if !$connection->can('check_hardware') || $connection->check_hardware;
+ if ($connection->can('configure_hardware')) {
+ my $_w = $in->wait_message(N("Please wait"), N("Configuring device..."));
+ if (!$connection->configure_hardware) {
+ $in->ask_warn(N("Error"), $connection->{hardware}{error}) if $connection->{hardware}{error};
+ return 1;
+ }
+ }
+ },
+ post => sub { $get_next->("configure_hardware") },
+ },
+
+ select_provider => {
+ pre => sub {
+ $provider_settings = $connection->get_provider_settings;
+ $connection->guess_provider_settings;
+ },
+ name => sub { $net->{type}->get_type_name . "\n\n" . N("Please select your provider:") },
+ data => sub { $provider_settings },
+ post => sub { $get_next->("select_provider") },
+ },
+
+ select_network => {
+ pre => sub {
+ my $_w = $in->wait_message(N("Please wait"), N("Scanning for networks..."));
+ $connection->get_networks($net);
+ },
+ name => sub { $net->{type}->get_type_name . "\n\n" . N("Please select your network:") },
+ data => sub {
+ [ { type => "list", val => \$connection->{network}, allow_empty_list => 1,
+ list => [ keys %{$connection->{networks}}, undef ],
+ format => sub { exists $connection->{networks}{$_[0]} ?
+ $connection->{networks}{$_[0]}{name} :
+ N("Unlisted - edit manually");
+ } } ];
+ },
+ post => sub {
+ $get_next->("select_network");
+ },
+ },
+
+ configure_network_access => {
+ pre => sub {
+ $network_access_settings = $connection->get_network_access_settings;
+ $connection->guess_network_access_settings if $connection->can('guess_network_access_settings');
+ },
+ name => sub { $net->{type}->get_type_name . "\n\n" . $connection->get_network_access_settings_label },
+ data => sub { $network_access_settings },
+ complete => sub {
+ if ($connection->can('check_network_access_settings') && !$connection->check_network_access_settings) {
+ $in->ask_warn(N("Error"), $connection->{network_access}{error}{message});
+ my $index = eval { find_index { $_->{val} eq $connection->{network_access}{error}{field} } @$network_access_settings };
+ return 1, $index;
+ }
+ return 0;
+ },
+ post => sub { $get_next->("configure_network_access") },
+ },
+
+ select_protocol => {
+ pre => sub {
+ $protocol_settings = $connection->get_protocol_settings;
+ $connection->guess_protocol($net) if $connection->can('guess_protocol');
+ },
+ name => sub { $net->{type}->get_type_name . "\n\n" . N("Please select your connection protocol.
+If you do not know it, keep the preselected protocol.") },
+ data => sub { $protocol_settings },
+ post => sub { $get_next->("select_protocol") },
+ },
+
+ configure_access => {
+ pre => sub {
+ $access_settings = $connection->get_access_settings;
+ $connection->guess_access_settings if $connection->can('guess_access_settings');
+ },
+ name => sub { $net->{type}->get_type_name . "\n\n" . $connection->get_access_settings_label },
+ data => sub { $access_settings },
+ post => sub { $get_next->("configure_access") },
+ },
+
+ configure_address => {
+ pre => sub {
+ $address_settings = $connection->can('get_address_settings') && $connection->get_address_settings;
+ $connection->guess_address_settings if $connection->can('guess_address_settings');
+ $connection->guess_hostname_settings if $connection->can('guess_hostname_settings');
+ $hostname_settings = $connection->can('get_hostname_settings') && $connection->get_hostname_settings;
+ },
+ name => sub { $net->{type}->get_type_name . "\n\n" . $connection->get_address_settings_label },
+ data => sub { [ @$address_settings, @$hostname_settings ] },
+ complete => sub {
+ if ($connection->can('check_address_settings') && !$connection->check_address_settings($net)) {
+ $in->ask_warn(N("Error"), $connection->{address}{error}{message});
+ my $index = eval { find_index { $_->{val} eq $connection->{address}{error}{field} } @$address_settings };
+ return 1, $index;
+ }
+ return 0;
+ },
+ post => sub { $get_next->("configure_address") },
+ },
+
+ configure_control => {
+ pre => sub {
+ $control_settings = $connection->get_control_settings;
+ $connection->can('get_network_control_settings') and
+ push @$control_settings, @{$connection->get_network_control_settings};
+ $connection->guess_control_settings if $connection->can('guess_control_settings');
+ $connection->guess_network_control_settings if $connection->can('guess_network_control_settings');
+ },
+ name => sub { $net->{type}->get_type_name . "\n\n" . N("Connection control") },
+ data => sub { $control_settings },
+ post => sub { $get_next->("configure_control") },
+ },
+
+ apply_connection => {
+ name => N("Do you want to start the connection now?"),
+ type => "yesorno",
+ complete => sub {
+ $connection->can('install_packages') && !$connection->install_packages($in);
+ },
+ post => sub {
+ my ($answer) = @_;
+ my $_w = $in->wait_message(N("Please wait"), N("Testing your connection..."), 1);
+ $connection->unload_connection if $connection->can('unload_connection');
+ $connection->write_settings($net, $modules_conf);
+ $connection->prepare_connection if $connection->can('prepare_connection');
+ if ($answer) {
+ $connection->disconnect;
+ $connection->connect;
+ # TODO: we should have some graphical notification for these tests
+ #- FIXME: should use network::test for ppp (after future merge with network::connection)
+ #- or start interface synchronously
+ if (!$::isInstall) {
+ services::start('network-up');
+ } else {
+ my $timeout = $connection->get_up_timeout;
+ while ($timeout--) {
+ my $status = $connection->get_status;
+ last if $status;
+ sleep 1;
+ }
+ }
+ $success = $connection->get_status();
+ # try to resolve the network address for some time
+ my $timeout = 3;
+ while ($timeout--) {
+ $has_internet = network::tools::connected();
+ last if $has_internet;
+ sleep 1;
+ }
+ }
+ "end"; #- handle disconnection in install?
+ },
+ },
+
+ isdn_account =>
+ {
+ pre => sub {
+ network::connection::isdn::get_info_providers_backend($isdn, $provider);
+ $isdn->{huptimeout} ||= 180;
+ },
+ name => N("Connection Configuration") . "\n\n" . N("Please fill or check the field below"),
+ data => sub {
+ [
+ { label => N("Your personal phone number"), val => \$isdn->{phone_in} },
+ { label => N("Provider name (ex provider.net)"), val => \$net->{resolv}{DOMAINNAME2} },
+ { label => N("Provider phone number"), val => \$isdn->{phone_out} },
+ { label => N("Provider DNS 1 (optional)"), val => \$net->{resolv}{dnsServer2} },
+ { label => N("Provider DNS 2 (optional)"), val => \$net->{resolv}{dnsServer3} },
+ { label => N("Dialing mode"), list => ["auto", "manual"], val => \$isdn->{dialing_mode} },
+ { label => N("Connection speed"), list => ["64 Kb/s", "128 Kb/s"], val => \$isdn->{speed} },
+ { label => N("Connection timeout (in sec)"), val => \$isdn->{huptimeout} },
+ { label => N("Account Login (user name)"), val => \$isdn->{login} },
+ { label => N("Account Password"), val => \$isdn->{passwd}, hidden => 1 },
+ { label => N("Card IRQ"), val => \$isdn->{irq}, advanced => 1 },
+ { label => N("Card mem (DMA)"), val => \$isdn->{mem}, advanced => 1 },
+ { label => N("Card IO"), val => \$isdn->{io}, advanced => 1 },
+ { label => N("Card IO_0"), val => \$isdn->{io0}, advanced => 1 },
+ { label => N("Card IO_1"), val => \$isdn->{io1}, advanced => 1 },
+ ];
+ },
+ post => sub {
+ network::connection::isdn::apply_config($in, $isdn);
+ $net->{net_interface} = 'ippp0';
+ "isdn_dial_on_boot";
+ },
+ },
+
+ isdn =>
+ {
+ pre=> sub {
+ detect($modules_conf, $net->{autodetect}, 'isdn');
+ %isdn_cards = map { $_->{description} => $_ } @{$net->{autodetect}{isdn}};
+ },
+ name => N("Select the network interface to configure:"),
+ data => sub {
+ [ { label => N("Net Device"), type => "list", val => \$isdn_name, allow_empty_list => 1,
+ list => [ $my_isdn, N("External ISDN modem"), keys %isdn_cards ] } ];
+ },
+ post => sub {
+ if ($isdn_name eq $my_isdn) {
+ return "isdn_ask";
+ } elsif ($isdn_name eq N("External ISDN modem")) {
+ $net->{type} = 'isdn_external';
+ return "modem";
+ }
+
+ # FIXME: some of these should be taken from isdn db
+ $isdn = { map { $_ => $isdn_cards{$isdn_name}{$_} } qw(description vendor id card_type driver type mem io io0 io1 irq firmware) };
+
+ if ($isdn->{id}) {
+ log::explanations("found isdn card : $isdn->{description}; vendor : $isdn->{vendor}; id : $isdn->{id}; driver : $isdn->{driver}\n");
+ $isdn->{description} =~ s/\|/ -- /;
+ }
+
+ network::connection::isdn::read_config($isdn);
+ $isdn->{driver} = $isdn_cards{$isdn_name}{driver}; #- do not let config overwrite default driver
+
+ #- let the user choose hisax or capidrv if both are available
+ $isdn->{driver} ne "capidrv" && network::connection::isdn::get_capi_card($in, $isdn) and return "isdn_driver";
+ return "isdn_protocol";
+ },
+ },
+
+
+ isdn_ask =>
+ {
+ pre => sub {
+ %isdn_cards = network::connection::isdn::get_cards();
+ },
+ name => N("Select a device!"),
+ data => sub { [ { label => N("Net Device"), val => \$isdn_name, type => 'list', separator => '|', list => [ keys %isdn_cards ], allow_empty_list => 1 } ] },
+ pre2 => sub {
+ my ($label) = @_;
+
+ #- ISDN card already detected
+ goto isdn_ask_step_3;
+
+ isdn_ask_step_1:
+ my $e = $in->ask_from_list_(N("ISDN Configuration"),
+ $label . "\n" . N("What kind of card do you have?"),
+ [ N_("ISA / PCMCIA"), N_("PCI"), N_("USB"), N_("I do not know") ]
+ ) or return;
+ isdn_ask_step_1b:
+ if ($e =~ /PCI/) {
+ $isdn->{card_type} = 'pci';
+ } elsif ($e =~ /USB/) {
+ $isdn->{card_type} = 'usb';
+ } else {
+ $in->ask_from_list_(N("ISDN Configuration"),
+ N("
+If you have an ISA card, the values on the next screen should be right.\n
+If you have a PCMCIA card, you have to know the \"irq\" and \"io\" of your card.
+"),
+ [ N_("Continue"), N_("Abort") ]) eq 'Continue' or goto isdn_ask_step_1;
+ $isdn->{card_type} = 'isa';
+ }
+
+ isdn_ask_step_2:
+ $e = $in->ask_from_listf(N("ISDN Configuration"),
+ N("Which of the following is your ISDN card?"),
+ sub { $_[0]{description} },
+ [ network::connection::isdn::get_cards_by_type($isdn->{card_type}) ]) or goto($isdn->{card_type} =~ /usb|pci/ ? 'isdn_ask_step_1' : 'isdn_ask_step_1b');
+ $e->{$_} and $isdn->{$_} = $e->{$_} foreach qw(driver type mem io io0 io1 irq firmware);
+
+ },
+ post => sub {
+ $isdn = $isdn_cards{$isdn_name};
+ return "isdn_protocol";
+ }
+ },
+
+
+ isdn_driver =>
+ {
+ pre => sub {
+ $isdn_name = "capidrv";
+ },
+ name => N("A CAPI driver is available for this modem. This CAPI driver can offer more capabilities than the free driver (like sending faxes). Which driver do you want to use?"),
+ data => sub { [
+ { label => N("Driver"), type => "list", val => \$isdn_name,
+ list => [ $isdn->{driver}, "capidrv" ] }
+ ] },
+ post => sub {
+ $isdn->{driver} = $isdn_name;
+ return "isdn_protocol";
+ }
+ },
+
+
+ isdn_protocol =>
+ {
+ name => N("ISDN Configuration") . "\n\n" . N("Which protocol do you want to use?"),
+ data => [
+ { label => N("Protocol"), type => "list", val => \$isdn_type,
+ list => [ keys %isdn_protocols ], format => sub { $isdn_protocols{$_[0]} } }
+ ],
+ post => sub {
+ $isdn->{protocol} = $isdn_type;
+ return "isdn_db";
+ }
+ },
+
+
+ isdn_db =>
+ {
+ name => N("ISDN Configuration") . "\n\n" . N("Select your provider.\nIf it is not listed, choose Unlisted."),
+ data => sub {
+ [ { label => N("Provider:"), type => "list", val => \$provider, separator => '|',
+ list => [ N("Unlisted - edit manually"), network::connection::isdn::read_providers_backend() ] } ];
+ },
+ next => "isdn_account",
+ },
+
+
+ no_supported_winmodem =>
+ {
+ name => N("Warning") . "\n\n" . N("Your modem is not supported by the system.
+Take a look at http://www.linmodems.org"),
+ end => 1,
+ },
+
+
+ modem =>
+ {
+ pre => sub {
+ require network::modem;
+ detect($modules_conf, $net->{autodetect}, 'modem');
+ $modem = {};
+ if ($net->{type} eq 'isdn_external') {
+ #- FIXME: seems to be specific to ZyXEL Adapter Omni.net/TA 128/Elite 2846i
+ #- it does not even work with TA 128 modems
+ #- http://bugs.mandrakelinux.com/query.php?bug=1033
+ $modem->{special_command} = 'AT&F&O2B40';
+ }
+ },
+ name => N("Select the modem to configure:"),
+ data => sub {
+ [ { label => N("Modem"), type => "list", val => \$modem_name, allow_empty_list => 1,
+ list => [ keys %{$net->{autodetect}{modem}}, N("Manual choice") ], } ];
+ },
+ complete => sub {
+ my $driver = $net->{autodetect}{modem}{$modem_name}{driver} or return 0;
+ #- some modem configuration programs modify modprobe.conf while we're loaded
+ #- so write it now and reload then
+ $modules_conf->write;
+ require network::connection::pots;
+ my $settings = network::thirdparty::apply_settings($in, 'pots', network::connection::pots::get_thirdparty_settings(), $driver);
+ $modem->{device} = $settings->{device} if $settings;
+ $modules_conf->read if $settings;
+ !$settings;
+ },
+ post => sub {
+ return 'choose_serial_port' if $modem_name eq N("Manual choice");
+ if (exists $net->{autodetect}{modem}{$modem_name}{device}) {
+ #- this is a serial probed modem
+ $modem->{device} = $net->{autodetect}{modem}{$modem_name}{device};
+ }
+ if (exists $modem->{device}) {
+ return "ppp_provider";
+ } else {
+ #- driver exists but device field hasn't been filled by network::thirdparty::setup_device
+ return "no_supported_winmodem";
+ }
+ },
+ },
+
+
+ choose_serial_port =>
+ {
+ pre => sub {
+ $modem->{device} ||= readlink "$::prefix/dev/modem";
+ },
+ name => N("Please choose which serial port your modem is connected to."),
+ if_(!$::isInstall, interactive_help_id => 'selectSerialPort'),
+ data => sub {
+ [ { val => \$modem->{device}, format => \&detect_devices::serialPort2text, type => "list",
+ list => [ grep { $_ ne $mouse->{device} } (detect_devices::serialPorts(), glob_("/dev/ttyUSB*"), grep { -e $_ } '/dev/modem', '/dev/ttySL0', '/dev/ttyS14',) ] } ];
+ },
+ post => sub {
+ return 'ppp_provider';
+ },
+ },
+
+
+ ppp_provider =>
+ {
+ pre => sub {
+ add2hash($modem, network::modem::ppp_read_conf());
+ $in->do_pkgs->ensure_is_installed('kppp-provider', $db_path);
+ my $p_db_path = "$::prefix$db_path";
+ @isp = map {
+ my $country = $_;
+ map {
+ s!$p_db_path/$country!!;
+ s/%([0-9]{3})/chr(int($1))/eg;
+ $countries{$country} ||= translate($country);
+ join('', $countries{$country}, $_);
+ } grep { !/.directory$/ } glob_("$p_db_path/$country/*");
+ } map { s!$p_db_path/!!o; s!_! !g; $_ } glob_("$p_db_path/*") if !@isp;
+ $old_provider = $provider;
+ },
+ name => N("Select your provider:"),
+ data => sub {
+ [ { label => N("Provider:"), type => "list", val => \$provider, separator => '/',
+ list => [ N("Unlisted - edit manually"), @isp ] } ];
+ },
+ post => sub {
+ if ($provider ne N("Unlisted - edit manually")) {
+ ($country, $provider) = split('/', $provider);
+ $country = { reverse %countries }->{$country};
+ my %l = getVarsFromSh("$::prefix$db_path/$country/$provider");
+ if (defined $old_provider && $old_provider ne $provider) {
+ $modem->{connection} = $l{Name};
+ $modem->{phone} = $l{Phonenumber};
+ $modem->{$_} = $l{$_} foreach qw(Authentication AutoName Domain Gateway IPAddr SubnetMask);
+ ($modem->{dns1}, $modem->{dns2}) = split(',', $l{DNS});
+ }
+ }
+ return "ppp_account";
+ },
+ },
+
+
+ ppp_account =>
+ {
+ name => N("Dialup: account options"),
+ data => sub {
+ [
+ { label => N("Connection name"), val => \$modem->{connection} },
+ { label => N("Phone number"), val => \$modem->{phone} },
+ { label => N("Login ID"), val => \$modem->{login} },
+ { label => N("Password"), val => \$modem->{passwd}, hidden => 1 },
+ { label => N("Authentication"), val => \$modem->{Authentication},
+ list => [ sort keys %ppp_auth_methods ], format => sub { $ppp_auth_methods{$_[0]} } },
+ ];
+ },
+ next => "ppp_ip",
+ },
+
+
+ ppp_ip =>
+ {
+ pre => sub {
+ $modem_dyn_ip = sub { $modem->{auto_ip} eq N("Automatic") };
+ },
+ name => N("Dialup: IP parameters"),
+ data => sub {
+ [
+ { label => N("IP parameters"), type => "list", val => \$modem->{auto_ip}, list => [ N("Automatic"), N("Manual") ] },
+ { label => N("IP address"), val => \$modem->{IPAddr}, disabled => $modem_dyn_ip },
+ { label => N("Subnet mask"), val => \$modem->{SubnetMask}, disabled => $modem_dyn_ip },
+ ];
+ },
+ next => "ppp_dns",
+ },
+
+
+ ppp_dns =>
+ {
+ pre => sub {
+ $modem_dyn_dns = sub { $modem->{auto_dns} eq N("Automatic") };
+ },
+ name => N("Dialup: DNS parameters"),
+ data => sub {
+ [
+ { label => N("DNS"), type => "list", val => \$modem->{auto_dns}, list => [ N("Automatic"), N("Manual") ] },
+ { label => N("Domain name"), val => \$modem->{domain}, disabled => $modem_dyn_dns },
+ { label => N("First DNS Server (optional)"), val => \$modem->{dns1}, disabled => $modem_dyn_dns },
+ { label => N("Second DNS Server (optional)"), val => \$modem->{dns2}, disabled => $modem_dyn_dns },
+ { text => N("Set hostname from IP"), val => \$modem->{AutoName}, type => 'bool', disabled => $modem_dyn_dns },
+ ];
+ },
+ next => "ppp_gateway",
+ },
+
+
+ ppp_gateway =>
+ {
+ name => N("Dialup: IP parameters"),
+ data => sub {
+ [
+ { label => N("Gateway"), type => "list", val => \$modem->{auto_gateway}, list => [ N("Automatic"), N("Manual") ] },
+ { label => N("Gateway IP address"), val => \$modem->{Gateway},
+ disabled => sub { $modem->{auto_gateway} eq N("Automatic") } },
+ ];
+ },
+ post => sub {
+ network::modem::ppp_configure($net, $in, $modem);
+ $net->{net_interface} = 'ppp0';
+ "configure_control_compat";
+ },
+ },
+
+
+ configure_control_compat => {
+ pre => sub {
+ $connection_compat = $net->{type}->new($connection || {});
+ network::connection::guess_control_settings($connection_compat);
+ $control_settings = network::connection::get_control_settings($connection_compat);
+ },
+ name => sub { N("Connection control") },
+ data => sub { $control_settings },
+ post => sub {
+ $net->{ifcfg}{$net->{net_interface}}{USERCTL} = bool2yesno($connection_compat->{control}{userctl});
+ $net->{ifcfg}{$net->{net_interface}}{ONBOOT} = bool2yesno($connection_compat->{control}{onboot});
+ network::network::configure_network($net, $in, $modules_conf);
+ "ask_connect_now";
+ },
+ },
+
+ isdn_dial_on_boot =>
+ {
+ pre => sub {
+ $net->{ifcfg}{ippp0} ||= {}; # we want the ifcfg-ippp0 file to be written
+ $net->{ifcfg}{ippp0}{DEVICE} = "ippp0";
+ @isdn_dial_methods = ({ name => N("Automatically at boot"),
+ ONBOOT => 1, DIAL_ON_IFUP => 1 },
+ { name => N("By using Net Applet in the system tray"),
+ ONBOOT => 0, DIAL_ON_IFUP => 1 },
+ { name => N("Manually (the interface would still be activated at boot)"),
+ ONBOOT => 1, DIAL_ON_IFUP => 0 });
+ my $method = find {
+ $_->{ONBOOT} eq text2bool($net->{ifcfg}{ippp0}{ONBOOT}) &&
+ $_->{DIAL_ON_IFUP} eq text2bool($net->{ifcfg}{ippp0}{DIAL_ON_IFUP});
+ } @isdn_dial_methods;
+ #- use net_applet by default
+ $isdn->{dial_method} = $method->{name} || $isdn_dial_methods[1]{name};
+ },
+ name => N("How do you want to dial this connection?"),
+ data => sub {
+ [ { type => "list", val => \$isdn->{dial_method}, list => [ map { $_->{name} } @isdn_dial_methods ] } ];
+ },
+ post => sub {
+ my $method = find { $_->{name} eq $isdn->{dial_method} } @isdn_dial_methods;
+ $net->{ifcfg}{ippp0}{$_} = bool2yesno($method->{$_}) foreach qw(ONBOOT DIAL_ON_IFUP);
+ return "configure_control_compat";
+ },
+ },
+
+ ask_connect_now =>
+ {
+ name => N("Do you want to try to connect to the Internet now?"),
+ type => "yesorno",
+ post => sub {
+ my ($a) = @_;
+ my $type = $net->{type};
+ $up = 1;
+ if ($a) {
+ # local $::isWizard = 0;
+ my $_w = $in->wait_message(N("Please wait"), N("Testing your connection..."), 1);
+ network::tools::stop_net_interface($net, 0);
+ sleep 1;
+ network::tools::start_net_interface($net, 1);
+ my $s = 30;
+ $type =~ /modem/ and $s = 50;
+ $type =~ /isdn/ and $s = 20;
+ sleep $s;
+ $up = network::tools::connected();
+ }
+ $success = $up;
+ return $a ? "disconnect" : "end";
+ }
+ },
+
+
+ disconnect =>
+ {
+ name => sub {
+ $up ? N("The system is now connected to the Internet.") .
+ if_($::isInstall, N("For security reasons, it will be disconnected now.")) :
+ N("The system does not seem to be connected to the Internet.
+Try to reconfigure your connection.");
+ },
+ no_back => 1,
+ end => 1,
+ post => sub {
+ $::isInstall and network::tools::stop_net_interface($net, 0);
+ return "end";
+ },
+ },
+
+
+ end =>
+ {
+ name => sub {
+ if (!$success) {
+ return join("\n\n", N("Problems occured during the network connectivity test."),
+ N("This can be caused by invalid network configuration, or problems with your modem or router."),
+ N("You might want to relaunch the configuration to verify the connection settings."));
+ }
+ if (!$has_internet) {
+ return join("\n\n", N("Congratulations, the network configuration is finished."), N("However, the Internet connectivity test failed. You should test your connection manually, and verify your Internet modem or router."),
+ N("If your connection does not work, you might want to relaunch the configuration."));
+ }
+ return join("\n\n", N("Congratulations, the network and Internet configuration are finished."), if_($::isStandalone && $in->isa('interactive::gtk'),
+ N("After this is done, we recommend that you restart your X environment to avoid any hostname-related problems.")));
+ },
+ end => 1,
+ },
+ },
+ });
+ $wiz->process($in);
+
+ #- keeping the translations in case someone want to restore these texts
+ if_(0,
+ N("Alcatel speedtouch USB modem"),
+ N("Sagem USB modem"),
+ N("Bewan modem"),
+ N("Bewan modem"),
+ N("ECI Hi-Focus modem"), # this one needs eci agreement
+ N("LAN connection"),
+ N("Wireless connection"),
+ N("ADSL connection"),
+ N("Cable connection"),
+ N("ISDN connection"),
+ N("Modem connection"),
+ N("DVB connection"),
+ # keep b/c of translations in case they can be reused somewhere else:
+ N("(detected on port %s)", 'toto'),
+ #-PO: here, "(detected)" string will be appended to eg "ADSL connection"
+ N("(detected %s)", 'toto'), N("(detected)"),
+ N("Network Configuration"),
+ N("Zeroconf hostname resolution"),
+ N("If desired, enter a Zeroconf hostname.
+This is the name your machine will use to advertise any of
+its shared resources that are not managed by the network.
+It is not necessary on most networks."),
+ N("Zeroconf Host name"),
+ N("Zeroconf host name must not contain a ."),
+ N("Because you are doing a network installation, your network is already configured.
+Click on Ok to keep your configuration, or cancel to reconfigure your Internet & Network connection.
+"),
+ N("The network needs to be restarted. Do you want to restart it?"),
+ N("A problem occurred while restarting the network: \n\n%s", 'foo'),
+ N("We are now going to configure the %s connection.\n\n\nPress \"%s\" to continue.", 'a', 'b'),
+ N("Configuration is complete, do you want to apply settings?"),
+ N("You have configured multiple ways to connect to the Internet.\nChoose the one you want to use.\n\n"),
+ N("Internet connection"),
+ N("Select the network interface to configure:"),
+ N("Configuring network device %s (driver %s)", '', ''),
+ N("The following protocols can be used to configure a LAN connection. Please choose the one you want to use."),
+ N("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."),
+ # better looking text (to be merged into texts since some languages (eg: ja) doesn't need it
+ N("Last but not least you can also type in your DNS server IP addresses."),
+ N("DNS server address should be in format 1.2.3.4"),
+ N("Gateway address should be in format 1.2.3.4"),
+ N("Gateway device"),
+ );
+}
+
+sub safe_main {
+ my ($net, $in, $modules_conf) = @_;
+ eval { real_main($net, $in, $modules_conf) };
+ my $err = $@;
+ if ($err) { # && $in->isa('interactive::gtk')
+ $err =~ /wizcancel/ and $in->exit(0);
+
+ local $::isEmbedded = 0; # to prevent sub window embedding
+ local $::isWizard = 0 if !$::isInstall; # to prevent sub window embedding
+ #err_dialog(N("Error"), N("An unexpected error has happened:\n%s", $err));
+ $in->ask_warn(N("Error"), N("An unexpected error has happened:\n%s", $err));
+ }
+}
+
+1;
+
+=head1 network::netconnect::detect()
+
+=head2 example of usage
+
+ use lib qw(/usr/lib/libDrakX);
+ use network::netconnect;
+ use modules;
+ use Data::Dumper;
+
+ my %i;
+ my $modules_conf = modules::any_conf->read;
+ network::netconnect::detect($modules_conf, \%i);
+ print Dumper(\%i),"\n";
+
+=cut
diff --git a/lib/network/network.pm b/lib/network/network.pm
new file mode 100644
index 0000000..24e1349
--- /dev/null
+++ b/lib/network/network.pm
@@ -0,0 +1,832 @@
+package network::network; # $Id$wir
+
+#-######################################################################################
+#- misc imports
+#-######################################################################################
+
+use strict;
+
+use lang;
+use Socket;
+use common;
+use run_program;
+use network::tools;
+use vars qw(@ISA @EXPORT);
+use log;
+
+our $network_file = "/etc/sysconfig/network";
+my $resolv_file = "/etc/resolv.conf";
+my $tmdns_file = "/etc/tmdns.conf";
+our $wireless_d = "/etc/sysconfig/network-scripts/wireless.d";
+
+# list of CRDA domains
+our @crda_domains = qw(AE AL AM AN AR AT AU AZ BA BE BG BH BL BN BO BR BY BZ CA CH CL CN CO CR CS CY CZ DE DK DO DZ EC EE EG ES FI FR GB GE GR GT HK HN HR HU ID IE IL IN IR IS IT JM JO JP KP KR KW KZ LB LI LK LT LU LV MA MC MK MO MT MX MY NL NO NP NZ OM PA PE PG PH PK PL PR PT QA RO RU SA SE SG SI SK SV SY TH TN TR TT TW UA US UY UZ VE VN YE ZA ZW);
+
+@ISA = qw(Exporter);
+@EXPORT = qw(addDefaultRoute dns dnsServers gateway guessHostname is_ip is_ip_forbidden masked_ip netmask resolv);
+
+#- $net hash structure
+#- autodetect
+#- type
+#- net_interface
+#- PROFILE: selected netprofile
+#- network (/etc/sysconfig/network) : NETWORKING FORWARD_IPV4 NETWORKING_IPV6 HOSTNAME GATEWAY GATEWAYDEV NISDOMAIN
+#- NETWORKING : networking flag : string : "yes" by default
+#- FORWARD_IPV4 : forward IP flag : string : "false" by default
+#- HOSTNAME : hostname : string : "localhost.localdomain" by default
+#- GATEWAY : gateway
+#- GATEWAYDEV : gateway interface
+#- NISDOMAIN : nis domain
+#- NETWORKING_IPV6 : use IPv6, "yes" or "no"
+#- IPV6_DEFAULTDEV
+#- resolv (/etc/resolv.conf): dnsServer, dnsServer2, dnsServer3, DOMAINNAME, DOMAINNAME2, DOMAINNAME3
+#- dnsServer : dns server 1
+#- dnsServer2 : dns server 2
+#- dnsServer3 : dns server 3 : note that we uses the dns1 for the LAN, and the 2 others for the internet conx
+#- DOMAINNAME : domainname : string : $net->{network}{HOSTNAME} =~ /\.(.*)/ by default
+#- DOMAINNAME2 : well it's another domainname : have to look further why we used 2
+#- adsl: bus, Encapsulation, vpi, vci provider_id, method, login, passwd, ethernet_device, capi_card
+#- cable: bpalogin, login, passwd
+#- zeroconf: hostname
+#- auth: LDAPDOMAIN WINDOMAIN
+#- ifcfg (/etc/sysconfig/network-scripts/ifcfg-*):
+#- key : device name
+#- value : hash containing ifcfg file values, see write_interface_conf() for an exhaustive list
+#- DHCP_HOSTNAME : If you have a dhcp and want to set the hostname
+#- IPADDR : IP address
+#- NETMASK : netmask
+#- DEVICE : device name
+#- BOOTPROTO : boot prototype : "bootp" or "dhcp" or "pump" or ...
+#- IPV6INIT
+#- IPV6TO4INIT
+#- MS_DNS1
+#- MS_DNS2
+#- DOMAIN
+
+sub read_conf {
+ my ($file) = @_;
+ +{ getVarsFromSh($file) };
+}
+
+sub read_resolv_conf_raw {
+ my ($o_file) = @_;
+ my $s = cat_($o_file || $::prefix . $resolv_file);
+ { nameserver => [ $s =~ /^\s*nameserver\s+(\S+)/mg ],
+ search => [ if_($s =~ /^\s*search\s+(.*)/m, split(' ', $1)) ] };
+}
+
+sub read_resolv_conf {
+ my ($o_file) = @_;
+ my $resolv_conf = read_resolv_conf_raw($o_file);
+ +{
+ (mapn { $_[0] => $_[1] } [ qw(dnsServer dnsServer2 dnsServer3) ], $resolv_conf->{nameserver}),
+ (mapn { $_[0] => $_[1] } [ qw(DOMAINNAME DOMAINNAME2 DOMAINNAME3) ], $resolv_conf->{search}),
+ };
+}
+
+sub read_interface_conf {
+ my ($file) = @_;
+ my %intf = getVarsFromSh($file);
+
+ $intf{BOOTPROTO} ||= 'static';
+ $intf{isPtp} = $intf{NETWORK} eq '255.255.255.255';
+ $intf{isUp} = 1;
+ \%intf;
+}
+
+sub read_zeroconf() {
+ cat_($::prefix . $tmdns_file) =~ /^\s*hostname\s*=\s*(\w+)/m && { ZEROCONF_HOSTNAME => $1 };
+}
+
+sub write_network_conf {
+ my ($net) = @_;
+
+ if ($net->{network}{HOSTNAME} && $net->{network}{HOSTNAME} =~ /\.(.+\..+)$/) {
+ $net->{resolv}{DOMAINNAME} ||= $1;
+ }
+ $net->{network}{NETWORKING} = 'yes';
+
+ setVarsInSh($::prefix . $network_file, $net->{network}, qw(HOSTNAME NETWORKING GATEWAY GATEWAYDEV NISDOMAIN FORWARD_IPV4 NETWORKING_IPV6 IPV6_DEFAULTDEV CRDA_DOMAIN));
+}
+
+sub write_zeroconf {
+ my ($net, $in) = @_;
+ my $zhostname = $net->{zeroconf}{hostname};
+ my $file = $::prefix . $tmdns_file;
+
+ if ($zhostname) {
+ $in->do_pkgs->ensure_binary_is_installed('tmdns', 'tmdns', 'auto') if !$in->do_pkgs->is_installed('bind');
+ $in->do_pkgs->ensure_binary_is_installed('zcip', 'zcip', 'auto');
+ }
+
+ #- write blank hostname even if disabled so that drakconnect does not assume zeroconf is enabled
+ eval { substInFile { s/^\s*(hostname)\s*=.*/$1 = $zhostname/ } $file } if $zhostname || -f $file;
+
+ require services;
+ services::set_status('tmdns', $net->{zeroconf}{hostname}, $::isInstall);
+}
+
+sub write_resolv_conf {
+ my ($net) = @_;
+ my $resolv = $net->{resolv};
+ my $file = $::prefix . $resolv_file;
+
+ my %new = (
+ search => [ grep { $_ } uniq(@$resolv{'DOMAINNAME', 'DOMAINNAME2', 'DOMAINNAME3'}) ],
+ nameserver => [ grep { $_ } uniq(@$resolv{'dnsServer', 'dnsServer2', 'dnsServer3'}) ],
+ );
+
+ my (%prev, @unknown);
+ foreach (cat_($file)) {
+ s/\s+$//;
+ s/^[#\s]*//;
+
+ if (my ($key, $val) = /^(search|nameserver)\s+(.*)$/) {
+ push @{$prev{$key}}, $val;
+ } elsif (/^ppp temp entry$/) {
+ } elsif (/\S/) {
+ push @unknown, $_;
+ }
+ }
+ unlink $file if -l $file; #- workaround situation when /etc/resolv.conf is an absolute link to /etc/ppp/resolv.conf or whatever
+
+ if (@{$new{search}} || @{$new{nameserver}}) {
+ $prev{$_} = [ difference2($prev{$_} || [], $new{$_}) ] foreach keys %new;
+
+ my @search = do {
+ my @new = if_(@{$new{search}}, "search " . join(' ', @{$new{search}}) . "\n");
+ my @old = if_(@{$prev{search}}, "# search " . join(' ', @{$prev{search}}) . "\n");
+ @new, @old;
+ };
+ my @nameserver = do {
+ my @new = map { "nameserver $_\n" } @{$new{nameserver}};
+ my @old = map { "# nameserver $_\n" } @{$prev{nameserver}};
+ @new, @old;
+ };
+ output_with_perm($file, 0644, @search, @nameserver, (map { "# $_\n" } @unknown), "\n# ppp temp entry\n");
+
+ #-res_init(); # reinit the resolver so DNS changes take affect
+ 1;
+ } else {
+ log::explanations("neither domain name nor dns server are configured");
+ 0;
+ }
+}
+
+sub update_broadcast_and_network {
+ my ($intf) = @_;
+ my @ip = split '\.', $intf->{IPADDR};
+ my @mask = split '\.', $intf->{NETMASK};
+ #- FIXME: NETWORK and BROADCAST are deprecated, see sysconfig.txt
+ $intf->{BROADCAST} = join('.', mapn { int($_[0]) | ((~int($_[1])) & 255) } \@ip, \@mask);
+ $intf->{NETWORK} = join('.', mapn { int($_[0]) & $_[1] } \@ip, \@mask);
+}
+
+sub write_interface_settings {
+ my ($intf, $file) = @_;
+ setVarsInSh($file, $intf, qw(DEVICE BOOTPROTO IPADDR NETMASK NETWORK BROADCAST GATEWAY ONBOOT HWADDR METRIC MII_NOT_SUPPORTED TYPE USERCTL ATM_ADDR ATM_DEVICE ETHTOOL_OPTS VLAN MTU DNS1 DNS2 DOMAIN RESOLV_MODS LINK_DETECTION_DELAY),
+ qw(WIRELESS_MODE WIRELESS_ESSID WIRELESS_NWID WIRELESS_FREQ WIRELESS_SENS WIRELESS_RATE WIRELESS_ENC_KEY WIRELESS_ENC_MODE WIRELESS_RTS WIRELESS_FRAG WIRELESS_IWCONFIG WIRELESS_IWSPY WIRELESS_IWPRIV WIRELESS_WPA_DRIVER WIRELESS_WPA_REASSOCIATE CRDA_DOMAIN),
+ qw(DVB_ADAPTER_ID DVB_NETWORK_DEMUX DVB_NETWORK_PID),
+ qw(IPV6INIT IPV6TO4INIT),
+ qw(MRU REMIP PPPOPTIONS HARDFLOWCTL DEFABORT RETRYTIMEOUT PAPNAME LINESPEED MODEMPORT DEBUG ESCAPECHARS INITSTRING),
+ qw(DISCONNECTTIMEOUT PERSIST DEFROUTE),
+ qw(VPN_NAME VPN_TYPE),
+ qw(ACCOUNTING),
+ qw(NM_CONTROLLED),
+ qw(UUID NAME LAST_CONNECT),
+ qw(CELLULAR_CID),
+ if_($intf->{BOOTPROTO} eq "dhcp", qw(DHCP_CLIENT DHCP_HOSTNAME NEEDHOSTNAME PEERDNS PEERYP PEERNTPD DHCP_TIMEOUT)),
+ if_($intf->{DEVICE} =~ /^ippp\d+$/, qw(DIAL_ON_IFUP))
+ );
+ substInFile { s/^DEVICE='(`.*`)'/DEVICE=$1/g } $file; #- remove quotes if DEVICE is the result of a command
+ chmod $intf->{WIRELESS_ENC_KEY} ? 0700 : 0755, $file; #- hide WEP key for non-root users
+ log::explanations("written $intf->{DEVICE} interface configuration in $file");
+}
+
+sub get_ifcfg_file {
+ my ($name) = @_;
+ "$::prefix/etc/sysconfig/network-scripts/ifcfg-$name";
+}
+
+sub write_interface_conf {
+ my ($net, $name) = @_;
+
+ my $file = get_ifcfg_file($name);
+ #- prefer ifcfg-XXX files
+ unlink("$::prefix/etc/sysconfig/network-scripts/$name");
+
+ my $intf = $net->{ifcfg}{$name};
+
+ require network::connection::ethernet;
+ my (undef, $mac_address) = network::connection::ethernet::get_eth_card_mac_address($intf->{DEVICE});
+ $intf->{HWADDR} &&= $mac_address; #- set HWADDR to MAC address if required
+
+ update_broadcast_and_network($intf);
+
+ defined($intf->{METRIC}) or $intf->{METRIC} = network::tools::get_default_metric(network::tools::get_interface_type($intf)),
+ $intf->{BOOTPROTO} =~ s/dhcp.*/dhcp/;
+
+ write_interface_settings($intf, $file);
+}
+
+sub write_wireless_conf {
+ my ($ssid, $ifcfg) = @_;
+ my $wireless_file = $::prefix . $wireless_d . '/' . $ssid;
+ my %wireless_ifcfg = %$ifcfg;
+ # FIXME: be smarter to keep only DHCP/IP settings here
+ delete $wireless_ifcfg{$_}
+ foreach qw(DEVICE MII_NOT_SUPPORTED ONBOOT);
+ write_interface_settings(\%wireless_ifcfg, $wireless_file);
+}
+
+sub add2hosts {
+ my ($hostname, @ips) = @_;
+ my ($sub_hostname) = $hostname =~ /(.*?)\./;
+
+ my $file = "$::prefix/etc/hosts";
+
+ my @l;
+ push(@l, [$_, $hostname, if_($sub_hostname, $sub_hostname)]) foreach(@ips);
+ foreach (cat_($file)) {
+ # strip our own comments
+ next if ($_ =~ /# generated by drak.*/);
+ my ($ip, $aliases) = /^\s*(\S+)\s+(\S+.*)$/ or next;
+ my @hosts = difference2([ split /\s+/, $aliases ], [ $hostname, $sub_hostname ]);
+ if (@hosts) {
+ push (@l, [$ip, @hosts]);
+ }
+ };
+
+ log::explanations("writing host information to $file");
+ output($file, "# generated by drakconnect\n");
+ foreach (@l) {
+ append_to_file($file, join(" ", @{$_}) . "\n");
+ }
+}
+
+# The interface/gateway needs to be configured before this will work!
+sub guessHostname {
+ my ($net, $intf_name) = @_;
+
+ $net->{ifcfg}{$intf_name}{isUp} && dnsServers($net) or return 0;
+ $net->{network}{HOSTNAME} && $net->{resolv}{DOMAINNAME} and return 1;
+
+ write_resolv_conf($net);
+
+ my $name = gethostbyaddr(Socket::inet_aton($net->{ifcfg}{$intf_name}{IPADDR}), Socket::AF_INET()) or log::explanations("reverse name lookup failed"), return 0;
+
+ log::explanations("reverse name lookup worked");
+
+ $net->{network}{HOSTNAME} ||= $name;
+ 1;
+}
+
+sub addDefaultRoute {
+ my ($net) = @_;
+ c::addDefaultRoute($net->{network}{GATEWAY}) if $net->{network}{GATEWAY};
+}
+
+sub write_hostname {
+ my ($hostname) = @_;
+
+ addVarsInSh($::prefix . $network_file, { HOSTNAME => $hostname }, qw(HOSTNAME));
+
+ add2hosts("localhost", "127.0.0.1");
+ add2hosts($hostname, "127.0.0.1") if $hostname;
+
+ unless ($::isInstall) {
+ my $rc = syscall_("sethostname", $hostname, length $hostname);
+ log::explanations($rc ? "set sethostname to $hostname" : "sethostname failed: $!");
+ run_program::run("/usr/bin/run-parts", "--arg", $hostname, "/etc/sysconfig/network-scripts/hostname.d");
+ }
+}
+
+sub resolv($) {
+ my ($name) = @_;
+ is_ip($name) and return $name;
+ my $a = join(".", unpack "C4", (gethostbyname $name)[4]);
+ #-log::explanations("resolved $name in $a");
+ $a;
+}
+
+sub dnsServers {
+ my ($net) = @_;
+ #- FIXME: that's weird
+ my %used_dns; @used_dns{$net->{network}{dnsServer}, $net->{network}{dnsServer2}, $net->{network}{dnsServer3}} = (1, 2, 3);
+ sort { $used_dns{$a} <=> $used_dns{$b} } grep { $_ } keys %used_dns;
+}
+
+sub findIntf {
+ my ($net, $device) = @_;
+ $net->{ifcfg}{$device}{DEVICE} = undef;
+ $net->{ifcfg}{$device};
+}
+
+my $ip_regexp = qr/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
+
+sub is_ip {
+ my ($ip) = @_;
+ my @fields = $ip =~ $ip_regexp or return;
+ every { 0 <= $_ && $_ <= 255 } @fields or return;
+ @fields;
+}
+
+sub ip_compare {
+ my ($ip1, $ip2) = @_;
+ my (@ip1_fields) = $ip1 =~ $ip_regexp;
+ my (@ip2_fields) = $ip2 =~ $ip_regexp;
+
+ every { $ip1_fields[$_] eq $ip2_fields[$_] } (0 .. 3);
+}
+
+sub is_ip_forbidden {
+ my ($ip) = @_;
+ my @forbidden = ('127.0.0.1', '255.255.255.255');
+
+ any { ip_compare($ip, $_) } @forbidden;
+}
+
+sub is_domain_name {
+ my ($name) = @_;
+ my @fields = split /\./, $name;
+ $name !~ /\.$/ && @fields > 0 && @fields == grep { /^[[:alnum:]](?:[\-[:alnum:]]{0,61}[[:alnum:]])?$/ } @fields;
+}
+
+sub netmask {
+ my ($ip) = @_;
+ return "255.255.255.0" unless is_ip($ip);
+ $ip =~ $ip_regexp or warn "IP_regexp failed\n" and return "255.255.255.0";
+ if ($1 >= 1 && $1 < 127) {
+ "255.0.0.0"; #-1.0.0.0 to 127.0.0.0
+ } elsif ($1 >= 128 && $1 <= 191) {
+ "255.255.0.0"; #-128.0.0.0 to 191.255.0.0
+ } elsif ($1 >= 192 && $1 <= 223) {
+ "255.255.255.0";
+ } else {
+ "255.255.255.255"; #-experimental classes
+ }
+}
+
+sub netmask_to_vlsm {
+ my ($netmask) = @_;
+ #- based on Network::IPv4Addr::ipv4_msk2cidr
+ my @bytes = split /\./, $netmask;
+ my $prefix = 0;
+ foreach (@bytes) {
+ my $bits = unpack("B*", pack("C", $_));
+ $prefix += $bits =~ tr/1/1/;
+ }
+ return $prefix;
+}
+
+sub masked_ip {
+ my ($ip) = @_;
+ my @ip = is_ip($ip) or return '';
+ my @mask = netmask($ip) =~ $ip_regexp;
+ for (my $i = 0; $i < @ip; $i++) {
+ $ip[$i] &= int $mask[$i];
+ }
+ join(".", @ip);
+}
+
+sub dns {
+ my ($ip) = @_;
+ my @masked = masked_ip($ip) =~ $ip_regexp;
+ $masked[3] = 1;
+ join(".", @masked);
+
+}
+
+sub gateway {
+ my ($ip) = @_;
+ my @masked = masked_ip($ip) =~ $ip_regexp;
+ $masked[3] = 1;
+ join(".", @masked);
+}
+
+sub netprofile_modules() {
+ my @m = split('\n', `/sbin/netprofile modules`);
+ my @modules = ();
+
+ foreach my $module (@m) {
+ my @params = split('\t', $module);
+ my $vals = {
+ module => @params[0],
+ enabled => @params[1] eq '+' ? 1 : 0,
+ name => @params[2],
+ description => @params[3],
+ };
+ push(@modules, $vals);
+ }
+ @modules;
+}
+
+sub netprofile_module_enable {
+ my ($module) = @_;
+ system('/sbin/netprofile', 'module_enable', $module);
+ log::explanations(qq(Enabling netprofile module $module));
+}
+
+sub netprofile_module_disable {
+ my ($module) = @_;
+ system('/sbin/netprofile', 'module_disable', $module);
+ log::explanations(qq(Disabling netprofile module $module));
+}
+
+sub netprofile_set {
+ my ($net, $profile) = @_;
+ $net->{PROFILE} = $profile;
+ system('/sbin/netprofile', 'switch', $net->{PROFILE});
+ log::explanations(qq(Switching to "$net->{PROFILE}" profile));
+}
+
+sub netprofile_delete {
+ my ($profile) = @_;
+ return if !$profile;
+ system('/sbin/netprofile', 'delete', $profile);
+ log::explanations(qq(Deleting "$profile" profile));
+}
+
+sub netprofile_list() {
+ map { if_(m!([^/]*)/$!, common::from_utf8($1)) } glob("$::prefix/etc/netprofile/profiles/*/");
+}
+
+sub netprofile_count() {
+ my @profiles = netprofile_list();
+ return $#profiles;
+}
+
+sub netprofile_read {
+ my ($net) = @_;
+ my $profile = cat_("$::prefix/etc/netprofile/current");
+ chomp $profile if $profile;
+ $net->{PROFILE} = $profile || 'default';
+}
+
+sub advanced_settings_read {
+ my $modprobe = "$::prefix/etc/modprobe.conf";
+ my $sysctl = "$::prefix/etc/sysctl.conf";
+ my $msecconf = "$::prefix/etc/security/msec/security.conf";
+
+ my $ipv6_disabled = grep { /^options ipv6 disable=1$/ } cat_($modprobe);
+ my $disable_window_scaling = grep { /^net\.ipv4\.tcp_window_scaling\s*=\s*0$/ } cat_($sysctl);
+ my $disable_tcp_timestamps = grep { /^net\.ipv4\.tcp_timestamps\s*=\s*0$/ } cat_($sysctl);
+ my $log_martians = grep { /^net\.ipv4\.conf\.all\.log_martians\s*=\s*1$/ } cat_($sysctl);
+ my $disable_icmp = grep { /^net\.ipv4\.icmp_echo_ignore_all\s*=\s*1$/ } cat_($sysctl);
+ my $disable_icmp_broadcasts = grep { /^net\.ipv4\.icmp_echo_ignore_broadcasts\s*=\s*1$/ } cat_($sysctl);
+ my $disable_bogus_error_responses = grep { /^net\.ipv4\.icmp_ignore_bogus_error_responses\s*=\s*1$/ } cat_($sysctl);
+ my $msec = grep { /^BASE_LEVEL=/ } cat_($msecconf);
+
+ { ipv6_disabled => $ipv6_disabled, disable_window_scaling => $disable_window_scaling,
+ disable_tcp_timestamps => $disable_tcp_timestamps, log_martians => $log_martians,
+ disable_icmp => $disable_icmp, disable_icmp_broadcasts => $disable_icmp_broadcasts,
+ disable_bogus_error_responses => $disable_bogus_error_responses,
+ msec => $msec,
+ }
+}
+
+sub advanced_settings_write {
+ my ($u) = @_;
+ # ipv6
+ substInFile {
+ /^(options ipv6 .*|install ipv6 .*|alias net-pf-10 off)/ and $_="";
+ if (eof and $u->{ipv6_disabled}) {
+ $_ .= "options ipv6 disable=1\n";
+ }
+ } "$::prefix/etc/modprobe.conf";
+ # sysctl
+ substInFile {
+ # remove old entries
+ /^net\.ipv4\.(tcp_window_scaling|tcp_timestamps|conf\.all\.log_martians|icmp_echo_ignore_all|icmp_echo_ignore_broadcasts|icmp_ignore_bogus_error_responses).*/ and $_="";
+ if (eof) {
+ # add new values
+ my $window_scaling = ($u->{disable_window_scaling}) ? "0" : "1";
+ my $tcp_timestamps = ($u->{disable_tcp_timestamps}) ? "0" : "1";
+ my $log_martians = ($u->{log_martians}) ? "1" : "0"; # this is inversed property
+ my $disable_icmp = ($u->{disable_icmp}) ? "1" : "0"; # this is inversed property
+ my $disable_icmp_broadcasts = ($u->{disable_icmp_broadcasts}) ? "1" : "0"; # this is inversed property
+ my $disable_bogus_error_responses = ($u->{disable_bogus_error_responses}) ? "1" : "0"; # this is inversed property
+ $_ .= "net.ipv4.tcp_window_scaling=$window_scaling\n";
+ $_ .= "net.ipv4.tcp_timestamps=$tcp_timestamps\n";
+ $_ .= "net.ipv4.conf.all.log_martians=$log_martians\n";
+ $_ .= "net.ipv4.icmp_echo_ignore_all=$disable_icmp\n";
+ $_ .= "net.ipv4.icmp_echo_ignore_broadcasts=$disable_icmp_broadcasts\n";
+ $_ .= "net.ipv4.icmp_ignore_bogus_error_responses=$disable_bogus_error_responses\n";
+ }
+ } "$::prefix/etc/sysctl.conf";
+}
+
+sub advanced_choose {
+ my ($in, $net, $u) = @_;
+
+ my $use_http_for_https = $u->{https_proxy} eq $u->{http_proxy};
+ $in->ask_from(N("Advanced network settings"),
+ N("Here you can configure advanced network settings. Please note that you have to reboot the machine for changes to take effect."),
+ [
+ { label => N("Wireless regulatory domain"), val => \$net->{network}{CRDA_DOMAIN}, sort => 1, list => \@crda_domains },
+ { label => "<b>".N("TCP/IP settings")."</b>"},
+ { text => N("Disable IPv6"), val => \$u->{ipv6_disabled}, type => "bool" },
+ { text => N("Disable TCP Window Scaling"), val => \$u->{disable_window_scaling}, type => "bool"},
+ { text => N("Disable TCP Timestamps"), val => \$u->{disable_tcp_timestamps}, type => "bool"},
+ { label => "<b>".N("Security settings (defined by MSEC policy)")."</b>"},
+ { text => N("Disable ICMP echo"), val => \$u->{disable_icmp}, type => "bool", disabled => sub { $u->{msec} }},
+ { text => N("Disable ICMP echo for broadcasting messages"), val => \$u->{disable_icmp_broadcasts}, type => "bool", disabled => sub { $u->{msec} }},
+ { text => N("Disable invalid ICMP error responses"), val => \$u->{disable_bogus_error_responses}, type => "bool", disabled => sub { $u->{msec} }},
+ { text => N("Log strange packets"), val => \$u->{log_martians}, type => "bool", disabled => sub { $u->{msec} }},
+ ]
+ ) or return;
+ 1;
+}
+
+sub miscellaneous_choose {
+ my ($in, $u) = @_;
+
+ my $net = {};
+ netprofile_read($net);
+
+ my $use_http_for_https = $u->{https_proxy} eq $u->{http_proxy};
+ $in->ask_from(N("Proxies configuration"),
+ N("Here you can set up your proxies configuration (eg: http://my_caching_server:8080)") . if_($net->{PROFILE} && netprofile_count() > 0, "\n".N("Those settings will be saved for the network profile <b>%s</b>", $net->{PROFILE})),
+ [ { label => N("HTTP proxy"), val => \$u->{http_proxy} },
+ { text => N("Use HTTP proxy for HTTPS connections"), val => \$use_http_for_https, type => "bool" },
+ { label => N("HTTPS proxy"), val => \$u->{https_proxy}, disabled => sub { $use_http_for_https } },
+ { label => N("FTP proxy"), val => \$u->{ftp_proxy} },
+ { label => N("No proxy for (comma separated list):"), val => \$u->{no_proxy} },
+ ],
+ complete => sub {
+ $use_http_for_https and $u->{https_proxy} = $u->{http_proxy};
+ $u->{no_proxy} =~ s/\s//g;
+ $u->{http_proxy} =~ m,^($|http://), or $in->ask_warn('', N("Proxy should be http://...")), return 1,0;
+ $u->{https_proxy} =~ m,^($|https?://), or $in->ask_warn('', N("Proxy should be http://... or https://...")), return 1,2;
+ $u->{ftp_proxy} =~ m,^($|ftp://|http://), or $in->ask_warn('', N("URL should begin with 'ftp:' or 'http:'")), return 1,3;
+ 0;
+ }
+ ) or return;
+ 1;
+}
+
+sub proxy_configure_shell {
+ my ($proxy) = @_;
+ my $sh_file = "$::prefix/etc/profile.d/proxy.sh";
+ setExportedVarsInSh($sh_file, $proxy, qw(http_proxy https_proxy ftp_proxy no_proxy));
+ chmod 0755, $sh_file;
+ my $csh_file = "$::prefix/etc/profile.d/proxy.csh";
+ setExportedVarsInCsh($csh_file, $proxy, qw(http_proxy https_proxy ftp_proxy no_proxy));
+ chmod 0755, $csh_file;
+}
+
+sub proxy_configure_kde {
+ my ($proxy) = @_;
+
+ my $kde_config_dir = "$::prefix/usr/share/config";
+ -d $kde_config_dir or return;
+
+ my $kde_config_file = "$kde_config_dir/kioslaverc";
+ update_gnomekderc($kde_config_file,
+ undef,
+ PersistentProxyConnection => "false"
+ );
+ update_gnomekderc($kde_config_file,
+ "Proxy Settings",
+ AuthMode => 0,
+ ProxyType => $proxy->{http_proxy} || $proxy->{https_proxy} || $proxy->{ftp_proxy} ? 4 : 0,
+ ftpProxy => "ftp_proxy",
+ httpProxy => "http_proxy",
+ httpsProxy => "https_proxy",
+ NoProxyFor => "no_proxy",
+ );
+}
+
+#- (protocol, user, password, host, port)
+my $http_proxy_match = qr,^(http)://(?:([^:\@]+)(?::([^:\@]+))?\@)?([^\:]+)(?::(\d+))?$,;
+#- (protocol, host, port)
+my $https_proxy_match = qr,^(https?)://(?:[^:\@]+(?::[^:\@]+)?\@)?([^\:]+)(?::(\d+))?$,;
+#- (protocol, protocol, host, port)
+my $ftp_proxy_match = qr,^(http|ftp)://(?:[^:\@]+(?::[^:\@]+)?\@)?([^\:]+)(?::(\d+))?$,;
+my %proxy_default_port = (
+ http => 80,
+ https => 443,
+ ftp => 21,
+);
+
+sub proxy_configure_gnome {
+ my ($proxy) = @_;
+
+ -d "$::prefix/etc/gconf/2/" or return;
+
+ my $defaults_dir = "/etc/gconf/gconf.xml.local-defaults";
+ my $p_defaults_dir = "$::prefix$defaults_dir";
+
+ my $use_alternate_proxy;
+ my $gconf_set = sub {
+ my ($key, $type, $value) = @_;
+ #- gconftool-2 is available since /etc/gconf/2/ exists
+ run_program::rooted($::prefix, 'gconftool-2', '>', '/dev/null', "--config-source=xml::$p_defaults_dir", "--direct", "--set", "--type=$type", if_($type eq "list", '--list-type', 'string'), $key, $value);
+ };
+
+ #- http proxy
+ if (my ($protocol, $user, $password, $host, $port) = $proxy->{http_proxy} =~ $http_proxy_match) {
+ $port ||= $proxy_default_port{$protocol} || $proxy_default_port{http};
+ $gconf_set->("/system/http_proxy/use_http_proxy", "bool", 1);
+ $gconf_set->("/system/http_proxy/host", "string", $host);
+ $gconf_set->("/system/http_proxy/port", "int", $port);
+ $gconf_set->("/system/http_proxy/use_authentication", "bool", to_bool($user));
+ $user and $gconf_set->("/system/http_proxy/authentication_user", "string", $user);
+ $password and $gconf_set->("/system/http_proxy/authentication_password", "string", $password);
+ } else {
+ $gconf_set->("/system/http_proxy/use_http_proxy", "bool", 0);
+ }
+
+ #- https proxy
+ if (my ($protocol, $host, $port) = $proxy->{https_proxy} =~ $https_proxy_match) {
+ $port ||= $proxy_default_port{$protocol} || $proxy_default_port{https};
+ $gconf_set->("/system/proxy/secure_host", "string", $host);
+ $gconf_set->("/system/proxy/secure_port", "int", $port);
+ $use_alternate_proxy = 1;
+ } else {
+ #- clear the ssl host so that it isn't used if the manual proxy is activated for ftp
+ $gconf_set->("/system/proxy/secure_host", "string", "");
+ }
+
+ #- ftp proxy
+ if (my ($protocol, $host, $port) = $proxy->{ftp_proxy} =~ $ftp_proxy_match) {
+ $port ||= $proxy_default_port{$protocol} || $proxy_default_port{ftp};
+ $gconf_set->("/system/proxy/ftp_host", "string", $host);
+ $gconf_set->("/system/proxy/ftp_port", "int", $port);
+ $use_alternate_proxy = 1;
+ } else {
+ #- clear the ftp host so that it isn't used if the manual proxy is activated for ssl
+ $gconf_set->("/system/proxy/ftp_host", "string", "");
+ }
+
+ my $ignore_hosts = join(',', uniq(qw(localhost 127.0.0.0/8)), split(',', $proxy->{no_proxy}));
+ $gconf_set->("/system/http_proxy/ignore_hosts", "list", "[$ignore_hosts]");
+
+ #- set proxy mode to manual if either https or ftp is used
+ $gconf_set->("/system/proxy/mode", "string", $use_alternate_proxy ? "manual" : "none");
+
+ #- make gconf daemons reload their settings
+ system("killall -s HUP gconfd-2");
+}
+
+sub proxy_configure_mozilla_firefox {
+ my ($proxy) = @_;
+
+ my $firefox_config_file = "$::prefix/etc/firefox.cfg";
+ -f $firefox_config_file or return;
+
+ my %prefs;
+ foreach (qw(http ssl ftp)) {
+ undef $prefs{"network.proxy.${_}"};
+ undef $prefs{"network.proxy.${_}_port"};
+ }
+ if (my ($protocol, undef, undef, $host, $port) = $proxy->{http_proxy} =~ $http_proxy_match) {
+ $prefs{"network.proxy.http"} = qq("$host");
+ $prefs{"network.proxy.http_port"} = $port || $proxy_default_port{$protocol} || $proxy_default_port{http};
+ }
+ if (my ($protocol, $host, $port) = $proxy->{https_proxy} =~ $https_proxy_match) {
+ $prefs{"network.proxy.ssl"} = qq("$host");
+ $prefs{"network.proxy.ssl_port"} = $port || $proxy_default_port{$protocol} || $proxy_default_port{https};
+ }
+ if (my ($protocol, $host, $port) = $proxy->{ftp_proxy} =~ $ftp_proxy_match) {
+ $prefs{"network.proxy.ftp"} = qq("$host");
+ $prefs{"network.proxy.ftp_port"} = $port || $proxy_default_port{$protocol} || $proxy_default_port{ftp};
+ }
+ if ($proxy->{no_proxy}) {
+ $prefs{"network.proxy.no_proxies_on"} = qq("$proxy->{no_proxy}");
+ }
+ $prefs{"network.proxy.type"} = any { defined $prefs{"network.proxy.${_}_port"} } qw(http ssl ftp);
+
+ substInFile {
+ while (my ($key, $value) = each(%prefs)) {
+ if (/^defaultPref\("$key",/) {
+ $_ = defined $value && qq(defaultPref("$key", $value);\n);
+ delete $prefs{$key};
+ }
+ }
+ $_ .= join('', map { if_(defined $prefs{$_}, qq(defaultPref("$_", $prefs{$_});\n)) } sort(keys %prefs)) if eof;
+ } $firefox_config_file;
+}
+
+sub proxy_configure {
+ my ($proxy) = @_;
+ proxy_configure_shell($proxy);
+ proxy_configure_kde($proxy);
+ proxy_configure_gnome($proxy);
+ proxy_configure_mozilla_firefox($proxy);
+}
+
+sub detect_crda_domain {
+ my $crda = { getVarsFromSh($::prefix . $network_file) }->{CRDA_DOMAIN};
+ if (!$crda) {
+ my $locale = lang::read($>);
+ my $country = $locale->{country};
+ if (grep($country, @crda_domains)) {
+ $crda = $country;
+ } else {
+ $crda = "US";
+ }
+ }
+ $crda;
+}
+
+sub read_net_conf {
+ my ($net) = @_;
+ add2hash($net->{network} ||= {}, read_conf($::prefix . $network_file));
+ add2hash($net->{resolv} ||= {}, read_resolv_conf());
+ add2hash($net->{zeroconf} ||= {}, read_zeroconf());
+
+ foreach (all("$::prefix/etc/sysconfig/network-scripts")) {
+ my ($device) = /^ifcfg-([A-Za-z0-9.:_-]+)$/;
+ next if $device =~ /.rpmnew$|.rpmsave$/;
+ if ($device && $device ne 'lo') {
+ my $intf = findIntf($net, $device);
+ add2hash($intf, { getVarsFromSh("$::prefix/etc/sysconfig/network-scripts/$_") });
+ $intf->{DEVICE} ||= $device;
+ }
+ }
+ $net->{wireless} ||= {};
+ foreach (all($::prefix . $wireless_d)) {
+ $net->{wireless}{$_} = { getVarsFromSh($::prefix . $wireless_d . '/' . $_) };
+ }
+ # detect default CRDA_DOMAIN
+ $net->{network}{CRDA_DOMAIN} ||= detect_crda_domain();
+ netprofile_read($net);
+ if (my $default_intf = network::tools::get_default_gateway_interface($net)) {
+ $net->{net_interface} = $default_intf;
+ $net->{type} = network::tools::get_interface_type($net->{ifcfg}{$default_intf});
+ }
+}
+
+#- FIXME: this is buggy, use network::tools::get_default_gateway_interface
+sub probe_netcnx_type {
+ my ($net) = @_;
+ #- try to probe $netcnx->{type} which is used almost everywhere.
+ unless ($net->{type}) {
+ #- ugly hack to determine network type (avoid saying not configured in summary).
+ -e "$::prefix/etc/ppp/peers/adsl" and $net->{type} ||= 'adsl'; # enough ?
+ -e "$::prefix/etc/ppp/ioptions1B" || -e "$::prefix/etc/ppp/ioptions2B" and $net->{type} ||= 'isdn'; # enough ?
+ $net->{ifcfg}{ppp0} and $net->{type} ||= 'modem';
+ $net->{ifcfg}{eth0} and $net->{type} ||= 'lan';
+ }
+}
+
+sub easy_dhcp {
+ my ($net, $modules_conf) = @_;
+
+ return if text2bool($net->{network}{NETWORKING});
+
+ require modules;
+ require network::connection::ethernet;
+ modules::load_category($modules_conf, list_modules::ethernet_categories());
+ my @all_dev = sort map { $_->[0] } network::connection::ethernet::get_eth_cards($modules_conf);
+
+ my @ether_dev = grep { /^eth[0-9]+$/ && `LC_ALL= LANG= $::prefix/sbin/ip -o link show $_ 2>/dev/null` =~ m|\slink/ether\s| } @all_dev;
+ foreach my $dhcp_intf (@ether_dev) {
+ log::explanations("easy_dhcp: found $dhcp_intf");
+ $net->{ifcfg}{$dhcp_intf} ||= {};
+ put_in_hash($net->{ifcfg}{$dhcp_intf}, {
+ DEVICE => $dhcp_intf,
+ BOOTPROTO => 'dhcp',
+ NETMASK => '255.255.255.0',
+ ONBOOT => 'yes'
+ });
+ }
+
+ 1;
+}
+
+sub reload_net_applet() {
+ #- make net_applet reload the configuration
+ my $pid = chomp_(`pidof -x net_applet`);
+ $pid and kill 1, $pid;
+}
+
+sub configure_network {
+ my ($net, $in, $modules_conf) = @_;
+ if (!$::testing) {
+ require network::connection::ethernet;
+ network::connection::ethernet::configure_eth_aliases($modules_conf);
+
+ write_network_conf($net);
+ write_resolv_conf($net);
+ write_hostname($net->{network}{HOSTNAME}) if $net->{network}{HOSTNAME};
+ foreach (keys %{$net->{ifcfg}}) {
+ write_interface_conf($net, $_);
+ my $ssid = $net->{ifcfg}{$_}{WIRELESS_ESSID} or next;
+ write_wireless_conf($ssid, $net->{ifcfg}{$_});
+ }
+ network::connection::ethernet::install_dhcp_client($in, $_->{DHCP_CLIENT}) foreach grep { $_->{BOOTPROTO} eq "dhcp" } values %{$net->{ifcfg}};
+ write_zeroconf($net, $in);
+
+ any { $_->{BOOTPROTO} =~ /^(pump|bootp)$/ } values %{$net->{ifcfg}} and $in->do_pkgs->install('pump');
+
+ require network::shorewall;
+ network::shorewall::update_interfaces_list();
+
+ }
+
+ reload_net_applet();
+}
+
+1;
diff --git a/lib/network/nfs.pm b/lib/network/nfs.pm
new file mode 100644
index 0000000..93df7ab
--- /dev/null
+++ b/lib/network/nfs.pm
@@ -0,0 +1,99 @@
+package network::nfs;
+
+use strict;
+use common;
+
+sub read_nfs_ports {
+ my $statd_port = 4001;
+ my $statd_outgoing_port = undef;
+ my $lockd_tcp_port = 4002;
+ my $lockd_udp_port = 4002;
+ my $rpc_mountd_port = 4003;
+ my $rpc_rquotad_port = 4004;
+ if (-f "$::prefix/etc/sysconfig/nfs-common") {
+ foreach (cat_("$::prefix/etc/sysconfig/nfs-common")) {
+ $_ =~ /^STATD_OPTIONS=.*(--port|-p) (\d+).*$/ and $statd_port = $2;
+ $_ =~ /^STATD_OPTIONS=.*(--outgoing-port|-o) (\d+).*$/ and $statd_outgoing_port = $2;
+ $_ =~ /^LOCKD_TCPPORT=(\d+)/ and $lockd_tcp_port = $1;
+ $_ =~ /^LOCKD_UDPPORT=(\d+)/ and $lockd_udp_port = $1;
+ }
+ }
+ if (-f "$::prefix/etc/sysconfig/nfs-server") {
+ foreach (cat_("$::prefix/etc/sysconfig/nfs-server")) {
+ $_ =~ /^RPCMOUNTD_OPTIONS=.*(--port|-p) (\d+).*$/ and $rpc_mountd_port = $2;
+ $_ =~ /^RPCRQUOTAD_OPTIONS=.*(--port|-p) (\d+).*$/ and $rpc_rquotad_port = $2;
+ }
+ }
+
+ my $ports = { statd_port => $statd_port,
+ lockd_tcp_port => $lockd_tcp_port,
+ lockd_udp_port => $lockd_udp_port,
+ rpc_mountd_port => $rpc_mountd_port,
+ rpc_rquotad_port => $rpc_rquotad_port,
+ };
+ if (defined $statd_outgoing_port) {
+ $ports->{statd_outgoing_port} => $statd_outgoing_port,
+ }
+ $ports;
+}
+
+sub list_nfs_ports {
+ my $ports = read_nfs_ports();
+
+ my $portlist = $ports->{lockd_tcp_port}. "/tcp " . $ports->{lockd_udp_port} . "/udp";
+ if (defined $ports->{statd_outgoing_port} and $ports->{statd_outgoing_port} ne $ports->{statd_port}) {
+ $portlist .= " " . $ports->{statd_outgoing_port} . "/tcp " . $ports->{statd_outgoing_port} . "/udp";
+ }
+ foreach (qw(statd_port rpc_mountd_port rpc_rquotad_port)) {
+ my $port = $ports->{$_};
+ $portlist .= " $port/tcp $port/udp";
+ }
+ # list of ports in shorewall format
+ $portlist;
+}
+
+sub write_nfs_ports {
+ my ($ports) = @_;
+ # enabling fixed ports for NFS services
+ # nfs-common
+ my $lockd_options="";
+ substInFile {
+ if ($ports->{statd_port}) {
+ my $port = $ports->{statd_port};
+ s/^(STATD_OPTIONS)=$/$1="--port $port"/;
+ s/^(STATD_OPTIONS)="(.*)(--port \d+)(.*)"$/$1="$2--port $port$4"/;
+ s/^(STATD_OPTIONS)="(.*)(-p \d+)(.*)"$/$1="$2--port $port$4"/;
+ }
+ if ($ports->{lockd_tcp_port}) {
+ my $port = $ports->{lockd_tcp_port};
+ s/^LOCKD_TCPPORT=.*/LOCKD_TCPPORT=$port/;
+ }
+ if ($ports->{lockd_udp_port}) {
+ my $port = $ports->{lockd_udp_port};
+ s/^LOCKD_UDPPORT=.*/LOCKD_UDPPORT=$port/;
+ }
+ } "$::prefix/etc/sysconfig/nfs-common";
+ # kernel-side configuration of nlockmgr
+ $lockd_options .= " nlm_tcpport=$ports->{lockd_tcp_port}" if $ports->{lockd_tcp_port};
+ $lockd_options .= " nlm_udpport=$ports->{lockd_udp_port}" if $ports->{lockd_udp_port};
+ if ($lockd_options ne "") {
+ output("$::prefix/etc/modprobe.d/lockd.drakx", "options lockd $lockd_options\n");
+ }
+ # nfs-server
+ substInFile {
+ if ($ports->{rpc_mountd_port}) {
+ my $port = $ports->{rpc_mountd_port};
+ s/^(RPCMOUNTD_OPTIONS)=$/$1="--port $port"/;
+ s/^(RPCMOUNTD_OPTIONS)="(.*)(--port \d+)(.*)"$/$1="$2--port $port$4"/;
+ s/^(RPCMOUNTD_OPTIONS)="(.*)(-p \d+)(.*)"$/$1="$2--port $port$4"/;
+ }
+ if ($ports->{rpc_rquotad_port}) {
+ my $port = $ports->{rpc_rquotad_port};
+ s/^(RPCRQUOTAD_OPTIONS)=$/$1="--port $port"/;
+ s/^(RPCRQUOTAD_OPTIONS)="(.*)(--port \d+)(.*)"$/$1="$2--port $port$4"/;
+ s/^(RPCRQUOTAD_OPTIONS)="(.*)(-p \d+)(.*)"$/$1="$2--port $port$4"/;
+ }
+ } "$::prefix/etc/sysconfig/nfs-server";
+}
+
+1;
diff --git a/lib/network/pxe.pm b/lib/network/pxe.pm
new file mode 100644
index 0000000..1bc625a
--- /dev/null
+++ b/lib/network/pxe.pm
@@ -0,0 +1,286 @@
+package network::pxe;
+
+use common;
+use network::tools;
+use Xconfig::resolution_and_depth;
+
+our $tftp_root = "/var/lib/tftpboot";
+my $client_path = '/X86PC/linux';
+our $pxelinux_client_root = $tftp_root . $client_path;
+our $pxelinux_images = $pxelinux_client_root . '/images';
+our $pxelinux_help_file = $pxelinux_client_root . '/help.txt';
+our $pxelinux_message_file = $pxelinux_client_root . '/messages';
+my $pxelinux_config_root = $pxelinux_client_root . '/pxelinux.cfg';
+our $pxelinux_config_file = $pxelinux_config_root . '/default';
+our $pxe_config_file = '/etc/pxe.conf';
+
+my @global_pxelinux_settings = qw(PROMPT DEFAULT DISPLAY TIMEOUT F1);
+my @append_settings = qw(initrd ramdisk_size vga display auto_install);
+my @automatic_settings = qw(method interface network server directory);
+
+our %vga_bios_to_resolution = (
+ 'normal' => "vga",
+ 'text' => "text",
+ '' => "automatic",
+ map { $_->{bios} => "$_->{X}x$_->{Y}" } grep { $_->{Depth} == 16 } Xconfig::resolution_and_depth::bios_vga_modes()
+ );
+our %vga_resolution_to_bios = reverse %vga_bios_to_resolution;
+
+sub read_pxelinux_help {
+ my ($help_file) = @_;
+ my %info;
+ foreach (cat_($help_file)) {
+ /^(\w+)\s*:\s*(.*)$/ and $info{$1} = $2;
+ }
+ \%info;
+}
+
+sub read_pxelinux_conf {
+ my ($conf_file, $help_file) = @_;
+ my (%conf);
+ my $info = read_pxelinux_help($help_file);
+ my $entry = {};
+ foreach (cat_($conf_file)) {
+ my $global = join('|', @global_pxelinux_settings);
+ if (/^($global)\s+(.*)/) {
+ $conf{lc($1)} = $2;
+ } elsif (/^label\s+(.*)/) {
+ $entry->{label} = $1;
+ } elsif (/^\s+LOCALBOOT\s+(\d+)/) {
+ $entry->{localboot} = $1;
+ } elsif (/^\s+KERNEL\s+(.*)/) {
+ $entry->{kernel} = $1;
+ } elsif (/^\s+APPEND\s+(.*)/) {
+ my @others;
+ foreach (split /\s+/, $1) {
+ my ($option, $value) = /^(.+?)(?:=(.*))?$/;
+ if (member($option, @append_settings)) {
+ $entry->{$option} = $value;
+ } elsif ($option eq 'automatic') {
+ foreach (split /,/, $value) {
+ my ($option, $value) = /^(.+?):(.+)$/;
+ $entry->{$option} = $value;
+ }
+ } else {
+ push @others, $_;
+ }
+ }
+ $entry->{others} = join(' ', @others);
+ }
+ if (exists $entry->{label} && (exists $entry->{localboot} || exists $entry->{kernel} && exists $entry->{initrd})) {
+ $entry->{info} = $info->{$entry->{label}};
+ push @{$conf{entries}}, $entry;
+ $entry = {};
+ }
+ }
+ \%conf;
+}
+
+
+sub list_pxelinux_labels {
+ my ($conf) = @_;
+ map { $_->{label} } @{$conf->{entries}};
+}
+
+sub write_pxelinux_conf {
+ my ($conf, $conf_file) = @_;
+
+ output($conf_file,
+ join("\n",
+ "# DO NOT EDIT auto_generated by drakpxelinux.pl",
+ (map { $_ . ' ' . $conf->{lc($_)} } @global_pxelinux_settings),
+ '',
+ (map {
+ my $e = $_;
+ my $automatic = join(',', map { "$_:$e->{$_}" } grep { $e->{$_} } @automatic_settings);
+ ("label $e->{label}",
+ exists $e->{localboot} ?
+ " LOCALBOOT $e->{localboot}" :
+ (" KERNEL $e->{kernel}",
+ " APPEND " . join(' ',
+ (map { "$_=$e->{$_}" } grep { $e->{$_} } @append_settings),
+ if_($automatic, "automatic=$automatic"),
+ $e->{others})),
+ '');
+ } @{$conf->{entries}})));
+}
+
+sub write_default_pxe_messages {
+ my ($net) = @_;
+ my $hostname = $net->{hostname} || chomp_(`hostname`);
+ output($pxelinux_message_file, <<EOF);
+
+ Welcome to Mandriva Linux PXE Server
+ Pxelinux
+ . .-----------------------------------.
+ /|\\ / Press F1 for available images \\
+ /_|_\\ \\ Hosted by $hostname
+ \\ | / _ /'-----------------------------------'
+ \\|/ (') /
+ '. U / (O__
+ . '. / (o_ (o_ (0_ //\\
+ {o_ (o_ (o_ (o_ (o_ //\\ //\\ //\\ // )
+ (')_ (`)_ (/)_ (/)_ (/)_ V_/_ V_/_ V_/_ V__/_
+ ---------------------------------------------------------
+
+ press F1 for help
+EOF
+}
+
+sub write_default_pxe_help() {
+ output($pxelinux_help_file, <<EOF);
+Available images are:
+---------------------
+local: local boot
+EOF
+}
+
+sub add_in_help {
+ my ($NAME, $INFO) = @_;
+ if (!any { /$NAME/ } cat_($pxelinux_help_file)) {
+ append_to_file($pxelinux_help_file, <<EOF);
+$NAME : $INFO
+EOF
+
+ } else {
+ substInFile {
+ s/$NAME.*/$NAME : $INFO/;
+ } $pxelinux_help_file;
+ }
+}
+
+sub change_label_in_help {
+ my ($NAMEOLD, $NEWNAME) = @_;
+ substInFile {
+ s/$NAMEOLD\s(.*)/$NEWNAME $1/;
+ } $pxelinux_help_file;
+}
+
+# remove entry in help.txt
+sub remove_in_help {
+ my ($NAME) = @_;
+ substInFile {
+ s/^$NAME\s:.*//x;
+ s/^\s*$//;
+ } $pxelinux_help_file;
+}
+
+# adjust pxe confi with good value
+sub write_pxe_conf {
+ my ($net, $interface) = @_;
+ if (!-f "$pxe_config_file.orig") { cp_af($pxe_config_file, "$pxe_config_file.orig") }
+ my $domainname = $net->{resolv}{domainname} || chomp_(`dnsdomainname`);
+ my $ip_address = network::tools::get_interface_ip_address($net, $interface);
+
+ substInFile {
+ s/default_address.*/default_address=$ip_address/;
+ s/mtftp_address.*/mtftp_address=$ip_address/;
+ s/domain.*/domain=$domainname/;
+ } $pxe_config_file;
+}
+
+
+sub get_pxelinux_config_file_for_mac_address {
+ my ($mac_address) = @_;
+ #- 01 is the hardware type: Ethernet (ARP type 1)
+ $pxelinux_config_root . "/" . join('-', '01', split(/:/, $mac_address));
+}
+
+sub set_profile_for_mac_address {
+ my ($profile, $to_install, $mac_address) = @_;
+ if ($profile) {
+ symlinkf("profiles/" . ($to_install ? "install/" : "boot/") . $profile, get_pxelinux_config_file_for_mac_address($mac_address));
+ } else {
+ unlink get_pxelinux_config_file_for_mac_address($mac_address);
+ }
+}
+
+#- returns (profile_type, profile_name)
+sub profile_from_file {
+ my ($file) = @_;
+ $file =~ m!(?:^|/)profiles/(\w+)/(.*)?$!;
+}
+
+sub read_profiles() {
+ my %profiles_conf;
+
+ foreach (all($pxelinux_config_root)) {
+ my $file = $pxelinux_config_root . '/' . $_;
+ if (-l $file && /^01(?:-([0-9a-z]{2}))+$/) {
+ #- per MAC address settings
+ #- the filename looks like 01-aa-bb-cc-dd-ee-ff
+ #- where AA:BB:CC:DD:EE:FF is the MAC address
+ my ($type, $name) = profile_from_file(readlink($file));
+ tr/-/:/;
+ my $mac_address = substr($_, 3);
+ $profiles_conf{per_mac}{$mac_address} = { profile => $name, to_install => $type eq 'install' };
+ }
+ }
+
+ foreach my $type (qw(boot install)) {
+ my $root = $pxelinux_config_root . '/profiles/' . $type;
+ mkdir_p($root);
+ $profiles_conf{profiles}{$type}{$_} = 1 foreach all($root);
+ }
+
+ \%profiles_conf;
+}
+
+#- returns (pxelinux entries file, help file)
+sub get_pxelinux_profile_path {
+ my ($profile, $type) = @_;
+ my $root = $pxelinux_config_root . '/profiles/' . $type;
+ "$root/$profile", "$root/help-$profile.txt";
+}
+
+sub list_profiles {
+ my ($profiles_conf) = @_;
+ sort(uniq(map { keys %{$profiles_conf->{profiles}{$_}} } qw(boot install)));
+}
+
+sub profile_exists {
+ my ($profiles_conf, $profile) = @_;
+ member($profile, network::pxe::list_profiles($profiles_conf));
+}
+
+sub find_next_profile_name {
+ my ($profiles_conf, $prefix) = @_;
+ my $i;
+ /^$prefix(\d*)$/ && $1 >= $i and $i = $1 + 1 foreach network::pxe::list_profiles($profiles_conf);
+ "$prefix$i";
+}
+
+sub add_empty_profile {
+ my ($profiles_conf, $profile, $to_install) = @_;
+ $to_install and $profiles_conf->{profiles}{install}{$profile} = 1;
+ $profiles_conf->{profiles}{boot}{$profile} = 1;
+}
+
+sub copy_profile_for_type {
+ my ($profile, $clone, $type) = @_;
+ my ($pxe, $help) = get_pxelinux_profile_path($profile, $type);
+ my ($clone_pxe, $clone_help) = get_pxelinux_profile_path($clone, $type);
+ -r $pxe and cp_f($pxe, $clone_pxe);
+ -r $help and cp_f($help, $clone_help);
+}
+
+sub clone_profile {
+ my ($profiles_conf, $profile) = @_;
+ my $clone = find_next_profile_name($profiles_conf, $profile);
+ if (exists $profiles_conf->{profiles}{install}{$profile}) {
+ $profiles_conf->{profiles}{install}{$clone} = 1;
+ copy_profile_for_type($profile, $clone, 'install');
+ }
+ $profiles_conf->{profiles}{boot}{$clone} = 1;
+ copy_profile_for_type($profile, $clone, 'boot');
+}
+
+sub remove_profile {
+ my ($profiles_conf, $profile) = @_;
+ foreach my $type (qw(boot install)) {
+ delete $profiles_conf->{profiles}{$type}{$profile};
+ unlink(get_pxelinux_profile_path($profile, $type));
+ }
+}
+
+1;
diff --git a/lib/network/rfswitch.pm b/lib/network/rfswitch.pm
new file mode 100644
index 0000000..4617990
--- /dev/null
+++ b/lib/network/rfswitch.pm
@@ -0,0 +1,38 @@
+package network::rfswitch;
+
+use strict;
+use MDK::Common;
+use detect_devices;
+
+my $conf_file = "/etc/modprobe.d/rfswitch.conf";
+
+my @settings = (
+ {
+ match => sub {
+ # CL56, with buggy BIOS
+ detect_devices::dmidecode_category('BIOS')->{Vendor} eq 'COMPAL' &&
+ detect_devices::dmidecode_category('System')->{'Product Name'} eq '<BAD INDEX>';
+ },
+ module => 'acerhk',
+ options => 'usedritek=1 autowlan=1 force_series=290',
+ install => 'echo 1 > /proc/driver/acerhk/wirelessled',
+ remove => 'echo 0 > /proc/driver/acerhk/wirelessled',
+ },
+);
+
+sub configure() {
+ my $setting = find { $_->{match}->() } @settings;
+ if ($setting) {
+ output_p($::prefix . $conf_file,
+ join("\n",
+ if_($setting->{options}, "options $setting->{module} $setting->{options}"),
+ if_($setting->{install}, "install $setting->{module} /sbin/modprobe --first-time --ignore-install $setting->{module} && $setting->{install}"),
+ if_($setting->{remove}, "remove $setting->{module} $setting->{remove}; /sbin/modprobe -r --ignore-remove $setting->{module}"),
+ "",
+ ));
+ require modules;
+ modules::set_preload_modules('rfswitch', $setting->{module});
+ }
+}
+
+1;
diff --git a/lib/network/shorewall.pm b/lib/network/shorewall.pm
new file mode 100644
index 0000000..da4e34d
--- /dev/null
+++ b/lib/network/shorewall.pm
@@ -0,0 +1,246 @@
+package network::shorewall; # $Id$
+
+use detect_devices;
+use network::network;
+use run_program;
+use common;
+use log;
+
+my $shorewall_root = "/etc/shorewall";
+our $firewall_icon = $::isInstall ? 'banner-security' : '/usr/share/mcc/themes/default/firewall-mdk.png';
+
+sub check_iptables() {
+ -f "$::prefix/etc/sysconfig/iptables" ||
+ $::isStandalone && do {
+ system('modprobe iptable_nat');
+ -x '/sbin/iptables' && listlength(`/sbin/iptables -t nat -nL`) > 8;
+ };
+}
+
+sub set_config_file {
+ my ($file, @l) = @_;
+
+ my $done;
+ substInFile {
+ if (!$done && (/^#LAST LINE/ || eof)) {
+ $_ = join('', map { join("\t", @$_) . "\n" } @l) . $_;
+ $done = 1;
+ } else {
+ $_ = '' if /^[^#]/;
+ }
+ } "$::prefix${shorewall_root}/$file";
+}
+
+sub get_config_file {
+ my ($file) = @_;
+ map { [ split ' ' ] } grep { !/^#/ } cat_("$::prefix${shorewall_root}/$file");
+}
+
+sub set_in_file {
+ my ($file, $enabled, @list) = @_;
+ my $done;
+ substInFile {
+ foreach my $l (@list) { s|^$l\n|| }
+ if (!$done && $enabled && (/^#LAST LINE/ || eof)) {
+ $_ = join('', map { "$_\n" } @list) . $_;
+ $done = 1;
+ }
+ } "$::prefix/etc/shorewall/$file";
+}
+
+sub dev_to_shorewall {
+ my ($dev) = @_;
+ $dev =~ /^ippp/ && "ippp+" ||
+ $dev =~ /^ppp/ && "ppp+" ||
+ $dev;
+}
+
+sub get_net_zone_interfaces {
+ my ($_net, $all_intf) = @_;
+ #- read shorewall configuration first
+ my @interfaces = map { $_->[1] } grep { $_->[0] eq 'net' } get_config_file('interfaces');
+ #- else try to find the best interface available
+ @interfaces ? @interfaces : @{$all_intf || []};
+}
+
+sub get_zones {
+ my ($conf, $o_in) = @_;
+ my $net = {};
+ network::network::read_net_conf($net);
+ #- find all interfaces but alias interfaces
+ my @all_intf = grep { !/:/ } uniq(keys(%{$net->{ifcfg}}), detect_devices::get_net_interfaces());
+ my %net_zone = map { $_ => undef } @all_intf;
+ $net_zone{$_} = 1 foreach get_net_zone_interfaces($net, \@all_intf);
+ $o_in and $o_in->ask_from_({
+ title => N("Firewall configuration"),
+ icon => $firewall_icon,
+ messages => N("Please select the interfaces that will be protected by the firewall.
+
+All interfaces directly connected to Internet should be selected,
+while interfaces connected to a local network may be unselected.
+
+If you intend to use Mandriva Internet Connection sharing,
+unselect interfaces which will be connected to local network.
+
+Which interfaces should be protected?
+"),
+ }, [
+ map {
+ { text => network::tools::get_interface_description($net, $_), val => \$net_zone{$_}, type => 'bool' };
+ } (sort keys %net_zone) ]);
+ ($conf->{net_zone}, $conf->{loc_zone}) = partition { $net_zone{$_} } keys %net_zone;
+}
+
+sub add_interface_to_net_zone {
+ my ($conf, $interface) = @_;
+ if (!member($interface, @{$conf->{net_zone}})) {
+ push @{$conf->{net_zone}}, $interface;
+ @{$conf->{loc_zone}} = grep { $_ ne $interface } @{$conf->{loc_zone}};
+ }
+}
+
+sub read {
+ my ($o_in) = @_;
+ #- read old rules file if config is not moved to rules.drakx yet
+ my @rules = get_config_file(-f "$::prefix${shorewall_root}/rules.drakx" ? 'rules.drakx' : 'rules');
+ my %conf = (disabled => !glob_("$::prefix/etc/rc3.d/S*shorewall"),
+ ports => join(' ', map {
+ my $e = $_;
+ map { "$_/$e->[3]" } split(',', $e->[4]);
+ } grep { $_->[0] eq 'ACCEPT' && $_->[1] eq 'net' } @rules),
+ );
+ push @{$conf{accept_local_users}{$_->[4]}}, $_->[8] foreach grep { $_->[0] eq 'ACCEPT+' } @rules;
+ $conf{redirects}{$_->[3]}{$_->[4]} = $_->[2] foreach grep { $_->[0] eq 'REDIRECT' } @rules;
+
+ if (my ($e) = get_config_file('masq')) {
+ ($conf{masq}{net_interface}, $conf{masq}{subnet}) = @$e;
+ }
+
+ my @policy = get_config_file('policy');
+ $conf{log_net_drop} = @policy ? (any { $_->[0] eq 'net' && $_->[1] eq 'all' && $_->[2] eq 'DROP' && $_->[3] } @policy) : 1;
+
+ get_zones(\%conf, $o_in);
+ get_config_file('zones') && \%conf;
+}
+
+sub ports_by_proto {
+ my ($ports) = @_;
+ my %ports_by_proto;
+ foreach (split ' ', $ports) {
+ m!^(\d+(?::\d+)?)/(udp|tcp|icmp)$! or die "bad port $_\n";
+ push @{$ports_by_proto{$2}}, $1;
+ }
+ \%ports_by_proto;
+}
+
+sub upgrade_to_shorewall3() {
+ #- the 'FW' option has been removed from shorewall.conf as of shorewall 3.0
+ my $ipsecfile_ok;
+ substInFile {
+ undef $_ if /^\s*FW=/;
+ if ((/^\s*IPSECFILE=/ || eof) && !$ipsecfile_ok) {
+ $ipsecfile_ok = 1;
+ $_ = "IPSECFILE=zones\n";
+ }
+ } "$::prefix${shorewall_root}/shorewall.conf";
+}
+
+sub write {
+ my ($conf, $o_in) = @_;
+ my $use_pptp = any { /^ppp/ && cat_("$::prefix/etc/ppp/peers/$_") =~ /pptp/ } @{$conf->{net_zone}};
+ my $ports_by_proto = ports_by_proto($conf->{ports});
+ my $has_loc_zone = to_bool(@{$conf->{loc_zone} || []});
+
+ my ($include_drakx, $other_rules) = partition { $_ eq "INCLUDE\trules.drakx\n" } grep { !/^#/ } cat_("$::prefix${shorewall_root}/rules");
+ #- warn if the config is already in rules.drakx and additionnal rules are configured
+ if (!is_empty_array_ref($include_drakx) && !is_empty_array_ref($other_rules)) {
+ my %actions = (
+ keep => N("Keep custom rules"),
+ drop => N("Drop custom rules"),
+ );
+ my $action = 'keep';
+ !$o_in || $o_in->ask_from_(
+ {
+ messages => N("Your firewall configuration has been manually edited and contains
+rules that may conflict with the configuration that has just been set up.
+What do you want to do?"),
+ title => N("Firewall"),
+ icon => 'banner-security',
+ },
+ [ { val => \$action, type => 'list', list => [ 'keep', 'drop' ], format => sub { $actions{$_[0]} } } ]) or return;
+ #- reset the rules files if the user has chosen to drop modifications
+ undef $include_drakx if $action eq 'drop';
+ }
+
+ my $interface_settings = sub {
+ my ($zone, $interface) = @_;
+ [ $zone, $interface, 'detect', if_(detect_devices::is_bridge_interface($interface), 'routeback') ];
+ };
+
+ set_config_file("zones",
+ [ 'net', 'ipv4' ],
+ if_($has_loc_zone, [ 'loc', 'ipv4' ]),
+ [ 'fw', 'firewall' ],
+ );
+ set_config_file('interfaces',
+ (map { $interface_settings->('net', $_) } @{$conf->{net_zone}}),
+ (map { $interface_settings->('loc', $_) } @{$conf->{loc_zone} || []}),
+ );
+ set_config_file('policy',
+ if_($has_loc_zone, [ 'loc', 'net', 'ACCEPT' ], [ 'loc', 'fw', 'ACCEPT' ], [ 'fw', 'loc', 'ACCEPT' ]),
+ [ 'fw', 'net', 'ACCEPT' ],
+ [ 'net', 'all', 'DROP', if_($conf->{log_net_drop}, 'info') ],
+ [ 'all', 'all', 'REJECT', 'info' ],
+ );
+ if (is_empty_array_ref($include_drakx)) {
+ #- make sure the rules.drakx config is read, erasing user modifications
+ set_config_file('rules', [ 'INCLUDE', 'rules.drakx' ]);
+ }
+ output_with_perm("$::prefix${shorewall_root}/" . 'rules.drakx', 0600, map { join("\t", @$_) . "\n" } (
+ if_($use_pptp, [ 'ACCEPT', 'fw', 'loc:10.0.0.138', 'tcp', '1723' ]),
+ if_($use_pptp, [ 'ACCEPT', 'fw', 'loc:10.0.0.138', 'gre' ]),
+ (map_each { [ 'ACCEPT', 'net', 'fw', $::a, join(',', @$::b), '-' ] } %$ports_by_proto),
+ (map_each {
+ if_($::b, map { [ 'ACCEPT+', 'fw', 'net', 'tcp', $::a, '-', '-', '-', $_ ] } @{$::b});
+ } %{$conf->{accept_local_users}}),
+ (map {
+ my $proto = $_;
+ #- WARNING: won't redirect ports from the firewall system if a local zone exists
+ #- set redirect_fw_only to workaround
+ map_each {
+ map { [ 'REDIRECT', $_, $::b, $proto, $::a, '-' ] } 'fw', if_($has_loc_zone, 'loc');
+ } %{$conf->{redirects}{$proto}};
+ } keys %{$conf->{redirects}}),
+ ));
+ set_config_file('masq', if_(exists $conf->{masq}, [ $conf->{masq}{net_interface}, $conf->{masq}{subnet} ]));
+
+ upgrade_to_shorewall3();
+
+ require services;
+ if ($conf->{disabled}) {
+ services::disable('shorewall', $::isInstall);
+ run_program::rooted($::prefix, '/sbin/shorewall', 'clear') unless $::isInstall;
+ } else {
+ services::enable('shorewall', $::isInstall);
+ }
+}
+
+sub set_redirected_ports {
+ my ($conf, $proto, $dest, @ports) = @_;
+ if (@ports) {
+ $conf->{redirects}{$proto}{$_} = $dest foreach @ports;
+ } else {
+ my $r = $conf->{redirects}{$proto};
+ @ports = grep { $r->{$_} eq $dest } keys %$r;
+ delete $r->{$_} foreach @ports;
+ }
+}
+
+sub update_interfaces_list {
+ my ($o_intf) = @_;
+ $o_intf && member($o_intf, map { $_->[1] } get_config_file('interfaces')) and return;
+ my $shorewall = network::shorewall::read();
+ $shorewall && !$shorewall->{disabled} and network::shorewall::write($shorewall);
+}
+
+1;
diff --git a/lib/network/signal_strength.pm b/lib/network/signal_strength.pm
new file mode 100644
index 0000000..19e119c
--- /dev/null
+++ b/lib/network/signal_strength.pm
@@ -0,0 +1,14 @@
+package network::signal_strength;
+
+use common;
+use ugtk2;
+
+my %pixbufs;
+
+sub get_strength_icon {
+ my ($network) = @_;
+ my $approx = 20 + min(80, int($network->{signal_strength}/20)*20);
+ return $pixbufs{$approx} ||= ugtk2::gtkcreate_pixbuf('wifi-' . sprintf('%03d', $approx));
+}
+
+1;
diff --git a/lib/network/squid.pm b/lib/network/squid.pm
new file mode 100644
index 0000000..427bce3
--- /dev/null
+++ b/lib/network/squid.pm
@@ -0,0 +1,74 @@
+package network::squid;
+
+use strict;
+use common;
+
+our $squid_conf_file = "$::prefix/etc/squid/squid.conf";
+
+sub read_squid_conf {
+ my ($o_file) = @_;
+ my $s = cat_($o_file || $squid_conf_file);
+ { http_port => [ $s =~ /^\s*http_port\s+(?:\S+:)?(\d+)\b/mg ],
+ cache_size => [ if_($s =~ /^\s*cache_dir diskd\s+(.*)/mg, split(' ', $1)) ],
+ admin_mail => [ if_($s =~ /^\s*err_html_text\s+(.*)/mg, split(' ', $1)) ] };
+}
+
+sub write_squid_conf {
+ my ($squid_conf, $intf, $internal_domain_name) = @_;
+
+ renamef($squid_conf_file, "$squid_conf_file.old");
+ my $prefix = network::network::netmask_to_vlsm($intf->{NETMASK});
+ output($squid_conf_file, qq(
+http_port $squid_conf->{http_port}[0] transparent
+hierarchy_stoplist cgi-bin ?
+acl QUERY urlpath_regex cgi-bin \\?
+no_cache deny QUERY
+cache_dir diskd /var/spool/squid $squid_conf->{cache_size}[1] 16 256
+cache_store_log none
+auth_param basic children 5
+auth_param basic realm Squid proxy-caching web server
+auth_param basic credentialsttl 2 hours
+refresh_pattern ^ftp: 1440 20% 10080
+refresh_pattern ^gopher: 1440 0% 1440
+refresh_pattern . 0 20% 4320
+half_closed_clients off
+acl manager proto cache_object
+acl localhost src 127.0.0.0/8
+acl to_localhost dst 127.0.0.0/8
+acl localnet src 10.0.0.0/8 # RFC1918 possible internal network
+acl localnet src 172.16.0.0/12 # RFC1918 possible internal network
+acl localnet src 192.168.0.0/16 # RFC1918 possible internal network
+acl SSL_ports port 443 563
+acl Safe_ports port 80 # http
+acl Safe_ports port 21 # ftp
+acl Safe_ports port 443 563 # https, snews
+acl Safe_ports port 70 # gopher
+acl Safe_ports port 210 # wais
+acl Safe_ports port 1025-65535 # unregistered ports
+acl Safe_ports port 280 # http-mgmt
+acl Safe_ports port 488 # gss-http
+acl Safe_ports port 591 # filemaker
+acl Safe_ports port 777 # multiling http
+acl CONNECT method CONNECT
+http_access allow manager localhost
+http_access deny manager
+http_access deny !Safe_ports
+http_access deny CONNECT !SSL_ports
+http_access deny to_localhost
+acl mynetwork src $intf->{NETWORK}/$prefix
+http_access allow mynetwork
+http_access allow localnet
+http_access allow localhost
+http_reply_access allow all
+icp_access allow all
+visible_hostname $squid_conf->{visible_hostname}[0]
+append_domain .$internal_domain_name
+err_html_text $squid_conf->{admin_mail}[0]
+deny_info ERR_CUSTOM_ACCESS_DENIED all
+memory_pools off
+coredump_dir /var/spool/squid
+ie_refresh on
+)) if !$::testing;
+}
+
+1;
diff --git a/lib/network/test.pm b/lib/network/test.pm
new file mode 100644
index 0000000..36da41d
--- /dev/null
+++ b/lib/network/test.pm
@@ -0,0 +1,161 @@
+package network::test; # $Id$
+
+use strict;
+use common;
+use run_program;
+use Socket;
+
+sub new {
+ my ($class, $o_hostname) = @_;
+ bless {
+ hostname => $o_hostname || "www.mandriva.com"
+ }, $class;
+}
+
+#- launch synchronous test, will hang until the test finishes
+sub test_synchronous {
+ my ($o) = @_;
+ ($o->{address}, $o->{ping}) = resolve_and_ping($o->{hostname});
+ $o->{done} = 1;
+}
+
+#- launch asynchronous test, will not hang
+sub start {
+ my ($o) = @_;
+ $o->{done} = 0;
+ $o->{kid} = bg_command->new(sub {
+ my ($address, $ping) = resolve_and_ping($o->{hostname});
+ print "$address|$ping\n";
+ });
+}
+
+#- abort asynchronous test
+sub abort {
+ my ($o) = @_;
+ if ($o->{kid}) {
+ kill -9, $o->{kid}{pid};
+ undef $o->{kid};
+ }
+}
+
+#- returns a true value if the test is finished, usefull for asynchronous tests
+sub is_done {
+ my ($o) = @_;
+ $o->update_status;
+ to_bool($o->{done});
+}
+
+#- return a true value if the connection works (hostname resolution and ping)
+sub is_connected {
+ my ($o) = @_;
+ to_bool(defined($o->{hostname}) && defined($o->{ping}));
+}
+
+#- get hostname used in test for resolution and ping
+sub get_hostname {
+ my ($o) = @_;
+ $o->{hostname};
+}
+
+#- get resolved address (if any) of given hostname
+sub get_address {
+ my ($o) = @_;
+ $o->{address};
+}
+
+#- get ping (if any) to given hostname
+sub get_ping {
+ my ($o) = @_;
+ $o->{ping};
+}
+
+sub resolve_and_ping {
+ my ($hostname) = @_;
+ require Net::Ping;
+ require Time::HiRes;
+ my $p;
+ if ($>) {
+ $p = Net::Ping->new('tcp');
+ # Try connecting to the www port instead of the echo port
+ $p->{port_num} = getservbyname('http', 'tcp');
+ } else {
+ $p = Net::Ping->new('icmp');
+ }
+ $p->hires; #- get ping as float
+ #- default timeout is 5 seconds
+ my ($ret, $ping, $address) = $p->ping($hostname, 5);
+ if ($ret) {
+ return $address, $ping;
+ } elsif (defined($ret)) {
+ return $address;
+ }
+}
+
+sub update_status {
+ my ($o) = @_;
+ if ($o->{kid}) {
+ my $fd = $o->{kid}{fd};
+ common::nonblock($fd);
+ local $| = 1;
+ if (defined(my $output = <$fd>)) {
+ ($o->{address}, $o->{ping}) = $output =~ /^([\d\.]+)\|([\d\.,]+)*$/;
+ $o->{done} = 1;
+ undef $o->{kid};
+ }
+ }
+}
+
+1;
+
+=head1 network::test
+
+=head2 Test synchronously
+
+resolve and get ping to hostname from command line if given, else to www.mandriva.com
+
+ use lib qw(/usr/lib/libDrakX);
+ use network::test;
+
+ my $net_test = network::test->new($ARGV[0]);
+ $net_test->test_synchronous;
+
+ my $is_connected = $net_test->is_connected;
+ my $hostname = $net_test->get_hostname;
+ my $address = $net_test->get_address;
+ my $ping = $net_test->get_ping;
+
+ print "connected: $is_connected
+ host: $hostname
+ resolved host: $address
+ ping to host: $ping
+ ";
+
+=head2 Test asynchronously
+
+resolve and get ping to hostname from command line if given, else to Mandriva
+
+prints a "." every 10 miliseconds during connection test
+
+ use lib qw(/usr/lib/libDrakX);
+ use network::test;
+
+ my $net_test = network::test->new($ARGV[0]);
+ $net_test->start;
+
+ do {
+ print ".\n";
+ select(undef, undef, undef, 0.01);
+ } while !$net_test->is_done;
+
+ my $is_connected = $net_test->is_connected;
+ my $hostname = $net_test->get_hostname;
+ my $address = $net_test->get_address;
+ my $ping = $net_test->get_ping;
+
+ print "connected: $is_connected
+ host: $hostname
+ resolved host: $address
+ ping to host: $ping
+ ";
+
+=cut
diff --git a/lib/network/thirdparty.pm b/lib/network/thirdparty.pm
new file mode 100644
index 0000000..f5a32eb
--- /dev/null
+++ b/lib/network/thirdparty.pm
@@ -0,0 +1,387 @@
+package network::thirdparty;
+
+use strict;
+use common;
+use detect_devices;
+use run_program;
+use services;
+use fs::get;
+use fs;
+use log;
+use modules;
+use list_modules;
+
+#- using bsd_glob() since glob("/DONT_EXIST") return "/DONT_EXIST" instead of () (and we don't want this)
+use File::Glob ':glob';
+
+#- network_settings is an hash of categories (rtc, dsl, wireless, ...)
+#- each category is an hash of device settings
+
+#- a device settings element must have the following fields:
+#- o matching:
+#- specify if this settings element matches a driver
+#- can be a regexp, array ref or Perl code (parameters: driver)
+#- o description:
+#- full name of the device
+#- o name: name used by the packages
+
+#- the following fields are optional:
+#- o url:
+#- url where the user can find tools/drivers/firmwares for this device
+#- o device:
+#- device in /dev to be configured
+#- o post:
+#- command to be run after all packages are installed
+#- can be a shell command or Perl code
+#- o restart_service:
+#- if exists but not 1, name of the service to be restarted
+#- if 1, specify that the service named by the name field should be restarted
+#- o tools:
+#- hash of the tools settings
+#- test_file field required
+#- if package field doesn't exist, 'name' is used
+#- o kernel_module:
+#- if exists but not 1, hash of the module settings
+#- if 1, kernel modules are needed and use the name field
+#- (name-kernel or dkms-name)
+#- o firmware:
+#- hash of the firmware settings
+#- test_file field required
+#- if package field doesn't exist, 'name-firmware' is used
+
+#- hash of package settings structure:
+#- o package:
+#- name of the package to be installed for these device
+#- o test_file:
+#- file used to test if the package is installed
+#- o prefix:
+#- path of the files that are tested
+#- o links:
+#- useful links for this device
+#- can be a single link or array ref
+#- o user_install:
+#- function to call if the package installation fails
+#- o explanations:
+#- additionnal text to display if the installation fails
+#- o no_distro_package:
+#- 1 if the package isn't available in the official distribution
+# (because of missing distribution rights for example)
+
+our $firmware_directory = "/lib/firmware";
+our @thirdparty_types = qw(kernel_module tools firmware);
+
+sub device_get_packages {
+ my ($settings, $component, $o_default) = @_;
+ $settings->{$component} or return;
+ my $package;
+ if (ref $settings->{$component} eq 'HASH') {
+ $package = $settings->{$component}{package} || 1;
+ } else {
+ $package = $settings->{$component};
+ }
+ $package == 1 ? $o_default || $settings->{name} : ref $package eq 'ARRAY' ? @$package : $package;
+}
+
+sub device_get_option {
+ my ($settings, $option, $o_default) = @_;
+ $settings->{$option} or return;
+ my $value = $settings->{$option};
+ $value == 1 ? $o_default || $settings->{name} : $value;
+}
+
+sub component_get_option {
+ my ($settings, $component, $option) = @_;
+ ref $settings->{$component} eq 'HASH' && $settings->{$component}{$option} || $settings->{$option};
+}
+
+sub find_settings {
+ my ($settings_list, $driver) = @_;
+ find {
+ my $match = $_->{matching} || $_->{name};
+ my $type = ref $match;
+ $type eq 'Regexp' && $driver =~ $match ||
+ $type eq 'CODE' && $match->($driver) ||
+ $type eq 'ARRAY' && member($driver, @$match) ||
+ $driver eq $match;
+ } @$settings_list;
+}
+
+sub device_run_command {
+ my ($settings, $driver, $component) = @_;
+ my $command = $settings->{$component} or return;
+
+ if (ref $command eq 'CODE') {
+ $command->($driver);
+ } else {
+ log::explanations("Running $component command $command");
+ run_program::rooted($::prefix, $command);
+ }
+}
+
+sub warn_not_installed {
+ my ($in, @packages) = @_;
+ $in->ask_warn(N("Error"), N("Could not install the packages (%s)!", join(', ', @packages)));
+}
+
+sub get_checked_element {
+ my ($settings, $driver, $component) = @_;
+ $component eq 'firmware' ?
+ get_firmware_path($settings) :
+ $component eq 'kernel_module' ?
+ $driver :
+ ref $settings->{$component} eq 'HASH' && $settings->{$component}{test_file};
+}
+
+sub warn_not_found {
+ my ($in, $settings, $driver, $component, @packages) = @_;
+ my %opt;
+ $opt{$_} = component_get_option($settings, $component, $_) foreach qw(url explanations no_distro_package no_package);
+ my $checked = get_checked_element($settings, $driver, $component);
+ my $component_name = ref $settings->{$component} eq 'HASH' && translate($settings->{$component}{component_name}) || $component;
+ $in->ask_warn(N("Error"),
+ join(" ",
+ ($opt{no_package} ?
+ N("Some components (%s) are required but aren't available for %s hardware.", $component_name, $settings->{name}) :
+ N("Some packages (%s) are required but aren't available.", join(', ', @packages))),
+ join("\n\n",
+ if_(!$opt{no_distro_package} && !$opt{no_package},
+ #-PO: first argument is a list of Mandriva distributions
+ #-PO: second argument is a package media name
+ N("These packages can be found in %s, or in the official %s package repository.",
+ join(", ", "Mandriva Linux One", "Mandriva Linux Powerpack"),
+ "non-free"),
+ ),
+ if_($checked, N("The following component is missing: %s", $checked)),
+ if_($opt{explanations}, translate($opt{explanations})),
+ if_($opt{url}, N("The required files can also be installed from this URL:
+%s", $opt{url})),
+ )));
+}
+
+sub is_file_installed {
+ my ($settings, $component) = @_;
+ my $file = ref $settings->{$component} eq 'HASH' && $settings->{$component}{test_file};
+ $file && -e "$::prefix$file";
+}
+
+sub is_module_installed {
+ my ($settings, $driver) = @_;
+ my $module = ref $settings->{kernel_module} eq 'HASH' && $settings->{kernel_module}{test_file} || $driver;
+ #- reload modules.dep so that newly added dkms modules are recognized
+ list_modules::load_default_moddeps();
+ #- FIXME: modules::module_is_available() won't use the chroot modules.dep in installer
+ modules::module_is_available($module);
+}
+
+sub get_firmware_path {
+ my ($settings) = @_;
+ my $wildcard = ref $settings->{firmware} eq 'HASH' && $settings->{firmware}{test_file} or return;
+ my $path = $settings->{firmware}{prefix} || $firmware_directory;
+ "$::prefix$path/$wildcard";
+}
+
+sub is_firmware_installed {
+ my ($settings) = @_;
+ my $pattern = get_firmware_path($settings) or return;
+ scalar bsd_glob($pattern, undef);
+}
+
+sub extract_firmware {
+ my ($settings, $in) = @_;
+ my $choice;
+ $in->ask_from('', N("Firmware files are required for this device."),
+ [ { type => "list", val => \$choice, format => \&translate,
+ list => [
+ if_(exists $settings->{firmware}{extract}{floppy_source}, N_("Use a floppy")),
+ if_(exists $settings->{firmware}{extract}{windows_source}, N_("Use my Windows partition")),
+ N_("Select file")
+ ] } ]) or return;
+ my ($h, $source);
+ if ($choice eq N_("Use a floppy")) {
+ $source = $settings->{firmware}{extract}{floppy_source};
+ $h = find_file_on_floppy($in, $source);
+ } elsif ($choice eq N_("Use my Windows partition")) {
+ $source = $settings->{firmware}{extract}{windows_source};
+ $h = find_file_on_windows_system($in, $source);
+ } else {
+ $source = $settings->{firmware}{extract}{default_source};
+ $h = { file => $in->ask_file(N("Please select the firmware file (for example: %s)", basename($source)), dirname($source)) };
+ }
+ if (!-e $h->{file}) {
+ log::explanations("Unable to find firmware file (tried to find $source.");
+ return;
+ }
+
+ if ($settings->{firmware}{extract}{name}) {
+ $in->do_pkgs->ensure_is_installed($settings->{firmware}{extract}{name}, $settings->{firmware}{extract}{test_file}) or return;
+ }
+ $settings->{firmware}{extract}{run}->($h->{file});
+ 1;
+}
+
+sub find_file_on_windows_system {
+ my ($in, $file) = @_;
+ my $source;
+ require fsedit;
+ my $all_hds = fsedit::get_hds();
+ fs::get_info_from_fstab($all_hds);
+ if (my $part = find { $_->{device_windobe} eq 'C' } fs::get::fstab($all_hds)) {
+ foreach (qw(windows/system winnt/system windows/system32/drivers winnt/system32/drivers)) {
+ -d $_ and $source = first(bsd_glob("$part->{mntpoint}/$_/$file", undef)) and last;
+ }
+ $source or $in->ask_warn(N("Error"), N("Unable to find \"%s\" on your Windows system!", $file));
+ } else {
+ $in->ask_warn(N("Error"), N("No Windows system has been detected!"));
+ }
+ { file => $source };
+}
+
+sub find_file_on_floppy {
+ my ($in, $file) = @_;
+ my $floppy = detect_devices::floppy();
+ my $mountpoint = '/media/floppy';
+ my $h;
+ $in->ask_okcancel(N("Insert floppy"),
+ N("Insert a FAT formatted floppy in drive %s with %s in root directory and press %s", $floppy, $file, N("Next"))) or return;
+ if (eval { fs::mount::mount(devices::make($floppy), $mountpoint, 'vfat', 'readonly'); 1 }) {
+ log::explanations("Mounting floppy device $floppy in $mountpoint");
+ $h = before_leaving { fs::mount::umount($mountpoint) };
+ if ($h->{file} = first(bsd_glob("$mountpoint/$file", undef))) {
+ log::explanations("Found $h->{file} on floppy device");
+ } else {
+ log::explanations("Unabled to find $file on floppy device");
+ }
+ } else {
+ $in->ask_warn(N("Error"), N("Floppy access error, unable to mount device %s", $floppy));
+ log::explanations("Unable to mount floppy device $floppy");
+ }
+ $h;
+}
+
+sub get_required_packages {
+ my ($type, $settings) = @_;
+ device_get_packages($settings, $type, if_($type eq 'firmware', "$settings->{name}-firmware"));
+}
+
+sub check_installed {
+ my ($type, $settings, $driver) = @_;
+ $type eq 'kernel_module' ?
+ is_module_installed($settings, $driver) :
+ $type eq 'firmware' ?
+ is_firmware_installed($settings) :
+ is_file_installed($settings, $type);
+}
+
+sub get_available_packages {
+ my ($type, $do_pkgs, @names) = @_;
+ if ($type eq 'kernel_module') {
+ return map { my $l = $do_pkgs->check_kernel_module_packages($_); $l ? @$l : () } @names;
+ } else {
+ return $do_pkgs->is_available(@names);
+ }
+}
+
+sub user_install {
+ my ($type, $settings, $in) = @_;
+ if ($type eq 'firmware') {
+ ref $settings->{$type} eq 'HASH' or return;
+ if ($settings->{$type}{extract}) {
+ extract_firmware($settings, $in);
+ } else {
+ my $f = $settings->{$type}{user_install};
+ $f && $f->($settings, $in);
+ }
+ } else {
+ my $f = ref $settings->{$type} eq 'HASH' && $settings->{$type}{user_install};
+ $f && $f->($settings, $in);
+ }
+}
+
+sub install_packages {
+ my ($in, $settings, $driver, $component, @packages) = @_;
+
+ unless (@packages) {
+ log::explanations(qq(No $component package for module "$driver" is required, skipping));
+ return 1;
+ }
+
+ if (check_installed($component, $settings, $driver)) {
+ $settings->{old_status}{$component} = 1;
+ log::explanations(qq(Required $component package for module "$driver" is already installed, skipping));
+ return 1;
+ }
+
+ my $optional = ref $settings->{$component} eq 'HASH' && $settings->{$component}{optional};
+ if (my @available = get_available_packages($component, $in->do_pkgs, @packages)) {
+ log::explanations("Installing thirdparty packages ($component) " . join(', ', @available));
+ if ($in->do_pkgs->install(@available) && check_installed($component, $settings, $driver)) {
+ return 1;
+ } elsif (!$optional) {
+ warn_not_installed($in, @available);
+ }
+ }
+ return 1 if $optional;
+ log::explanations("Thirdparty package @packages ($component) is required but not available");
+
+ 0;
+}
+
+sub install_components {
+ my ($in, $settings, $driver, @components) = @_;
+
+ foreach my $component (@components) {
+ my @packages = get_required_packages($component, $settings);
+ if (!component_get_option($settings, $component, 'no_package')) {
+ install_packages($in, $settings, $driver, $component, @packages) and next;
+ }
+
+ unless (user_install($component, $settings, $in)) {
+ warn_not_found($in, $settings, $driver, $component, @packages);
+ return;
+ }
+ }
+
+ 1;
+}
+
+sub apply_settings {
+ my ($in, $category, $settings_list, $driver) = @_;
+
+ my $settings = find_settings($settings_list, $driver);
+ if ($settings) {
+ log::explanations(qq(Found settings for driver "$driver" in category "$category"));
+
+ my $wait = $in->wait_message(N("Please wait"), N("Looking for required software and drivers..."));
+
+ install_components($in, $settings, $driver, @thirdparty_types) or return;
+
+ if (!$settings->{no_module_reload}) {
+ if (exists $settings->{firmware} && !$settings->{old_status}{firmware}) {
+ log::explanations("Reloading module $driver");
+ eval { modules::unload($driver) };
+ } else {
+ log::explanations("Loading module $driver");
+ }
+ eval { modules::load($driver) };
+ }
+
+ undef $wait;
+ $wait = $in->wait_message(N("Please wait"), N("Please wait, running device configuration commands..."));
+ device_run_command($settings, $driver, 'post');
+
+ if (my $service = device_get_option($settings, 'restart_service')) {
+ log::explanations("Restarting service $service");
+ services::restart_or_start($service);
+ }
+
+ $settings->{sleep} and sleep $settings->{sleep};
+
+ log::explanations(qq(Settings for driver "$driver" applied));
+ } else {
+ log::explanations(qq(No settings found for driver "$driver" in category "$category"));
+ }
+
+ $settings || {};
+}
+
+1;
diff --git a/lib/network/tools.pm b/lib/network/tools.pm
new file mode 100644
index 0000000..0a1d840
--- /dev/null
+++ b/lib/network/tools.pm
@@ -0,0 +1,278 @@
+package network::tools; # $Id$
+
+use strict;
+use common;
+use run_program;
+use c;
+use Socket;
+
+sub write_secret_backend {
+ my ($login, $password) = @_;
+ require network::connection::ppp;
+ network::connection::ppp::write_secrets({ access => { login => $login, password => $password } });
+}
+
+sub passwd_by_login {
+ my ($login) = @_;
+ require network::connection::ppp;
+ network::connection::ppp::get_secret(undef, $login);
+}
+
+sub run_interface_command {
+ my ($command, $intf, $detach) = @_;
+ my @command =
+ !$> || system("/usr/sbin/usernetctl $intf report") == 0 ?
+ ($command, $intf, if_(!$::isInstall, "daemon")) :
+ common::wrap_command_for_root($command, $intf);
+ run_program::raw({ detach => $detach, root => $::prefix }, @command);
+}
+
+sub start_interface {
+ my ($intf, $detach) = @_;
+ run_interface_command('/sbin/ifup', $intf, $detach);
+}
+
+sub stop_interface {
+ my ($intf, $detach) = @_;
+ run_interface_command('/sbin/ifdown', $intf, $detach);
+}
+
+sub start_net_interface {
+ my ($net, $detach) = @_;
+ start_interface($net->{net_interface}, $detach);
+}
+
+sub stop_net_interface {
+ my ($net, $detach) = @_;
+ stop_interface($net->{net_interface}, $detach);
+}
+
+sub connected() { gethostbyname("www.mandriva.com") ? 1 : 0 }
+
+# request a ref on a bg_connect and a ref on a scalar
+sub connected_bg__raw {
+ my ($kid_pipe, $status) = @_;
+ local $| = 1;
+ if (ref($kid_pipe) && ref($$kid_pipe)) {
+ my $fd = $$kid_pipe->{fd};
+ common::nonblock($fd);
+ my $a = <$fd>;
+ $$status = $a if defined $a;
+ } else { $$kid_pipe = check_link_beat() }
+}
+
+my $kid_pipe;
+sub connected_bg {
+ my ($status) = @_;
+ connected_bg__raw(\$kid_pipe, $status);
+}
+
+# test if connected;
+# cmd = 0 : ask current status
+# return : 0 : not connected; 1 : connected; -1 : no test ever done; -2 : test in progress
+# cmd = 1 : start new connection test
+# return : -2
+# cmd = 2 : cancel current test
+# return : nothing
+# cmd = 3 : return current status even if a test is in progress
+my $kid_pipe_connect;
+my $current_connection_status;
+
+sub test_connected {
+ local $| = 1;
+ my ($cmd) = @_;
+
+ $current_connection_status = -1 if !defined $current_connection_status;
+
+ if ($cmd == 0) {
+ connected_bg__raw(\$kid_pipe_connect, \$current_connection_status);
+ } elsif ($cmd == 1) {
+ if ($current_connection_status != -2) {
+ $current_connection_status = -2;
+ $kid_pipe_connect = check_link_beat();
+ }
+ } elsif ($cmd == 2) {
+ if (defined($kid_pipe_connect)) {
+ kill -9, $kid_pipe_connect->{pid};
+ undef $kid_pipe_connect;
+ }
+ }
+ return $current_connection_status;
+}
+
+sub check_link_beat() {
+ bg_command->new(sub {
+ require Net::Ping;
+ my $p;
+ if ($>) {
+ $p = Net::Ping->new("tcp");
+ # Try connecting to the www port instead of the echo port
+ $p->{port_num} = getservbyname("http", "tcp");
+ } else {
+ $p = Net::Ping->new("icmp");
+ }
+ print $p->ping("www.mandriva.com") ? 1 : 0;
+ });
+}
+
+sub is_dynamic_ip {
+ my ($net) = @_;
+ any { $_->{BOOTPROTO} !~ /^(none|static|)$/ } values %{$net->{ifcfg}};
+}
+
+sub is_dynamic_host {
+ my ($net) = @_;
+ any { defined $_->{DHCP_HOSTNAME} } values %{$net->{ifcfg}};
+}
+
+#- returns interface whose IP address matchs given IP address, according to its network mask
+sub find_matching_interface {
+ my ($net, $address) = @_;
+ my @ip = split '\.', $address;
+ find {
+ my @intf_ip = split '\.', $net->{ifcfg}{$_}{IPADDR} or return;
+ my @mask = split '\.', $net->{ifcfg}{$_}{NETMASK} or return;
+ every { $_ } mapn { ($_[0] & $_[2]) == ($_[1] & $_[2]) } \@intf_ip, \@ip, \@mask;
+ } sort keys %{$net->{ifcfg}};
+}
+
+#- returns the current gateway, with lowest metric
+sub get_current_gateway_interface() {
+ my $routes = get_routes();
+ first(sort { $routes->{$a}{metric} <=> $routes->{$b}{metric} } grep {
+ $routes->{$_}{network} eq '0.0.0.0' && $routes->{$_}{gateway};
+ } keys %$routes);
+}
+
+#- returns gateway interface if found
+sub get_default_gateway_interface {
+ my ($net) = @_;
+ my @intfs = sort keys %{$net->{ifcfg}};
+ get_current_gateway_interface() ||
+ $net->{network}{GATEWAYDEV} ||
+ $net->{network}{GATEWAY} && find_matching_interface($net, $net->{network}{GATEWAY}) ||
+ (find { get_interface_type($net->{ifcfg}{$_}) eq 'adsl' } @intfs) ||
+ (find { get_interface_type($net->{ifcfg}{$_}) eq 'isdn' && text2bool($net->{ifcfg}{$_}{DIAL_ON_IFUP}) } @intfs) ||
+ (find { get_interface_type($net->{ifcfg}{$_}) eq 'modem' } @intfs) ||
+ (find { get_interface_type($net->{ifcfg}{$_}) eq 'wifi' && $net->{ifcfg}{$_}{BOOTPROTO} eq 'dhcp' } @intfs) ||
+ (find { get_interface_type($net->{ifcfg}{$_}) eq 'ethernet' && $net->{ifcfg}{$_}{BOOTPROTO} eq 'dhcp' } @intfs);
+}
+
+#- remove suffix from virtual interfaces
+sub get_real_interface {
+ my ($intf) = @_;
+ $intf =~ s/:\d+$//;
+ $intf;
+}
+
+sub is_virtual_interface {
+ my ($intf) = @_;
+ $intf =~ /:\d+$/;
+}
+
+sub is_vlan_interface {
+ my ($intf) = @_;
+ $intf =~ /\.\d+$/;
+}
+
+sub is_real_interface {
+ my ($intf) = @_;
+ !is_virtual_interface($intf) && !is_vlan_interface($intf);
+}
+
+sub is_zeroconf_interface {
+ my ($intf) = @_;
+ is_virtual_interface($intf) && get_interface_ip_address({}, $intf) =~ /^(127|169\.254)\./;
+}
+
+sub get_interface_status {
+ my ($intf) = @_;
+ $intf = get_real_interface($intf);
+ my $routes = get_routes();
+ return $routes->{$intf}{network}, $routes->{$intf}{network} eq '0.0.0.0' && $routes->{$intf}{gateway};
+}
+
+#- returns (gateway_interface, interface is up, gateway address, dns server address)
+sub get_default_connection {
+ my ($net, $o_gw_intf) = @_;
+ my $gw_intf = $o_gw_intf || get_default_gateway_interface($net) or return;
+ $net->{resolv} = {};
+ require network::network;
+ add2hash($net->{resolv}, network::network::read_resolv_conf());
+ return $gw_intf, get_interface_status($gw_intf), $net->{resolv}{dnsServer};
+}
+
+sub has_network_connection() {
+ (undef, undef, my $gw_address) = get_default_connection({});
+ to_bool($gw_address);
+}
+
+sub get_interface_type {
+ my ($interface, $o_module) = @_;
+ require detect_devices;
+ member($interface->{TYPE}, "xDSL", "ADSL") && "adsl" ||
+ $interface->{DEVICE} =~ /^ippp/ && "isdn" ||
+ $interface->{DEVICE} =~ /^ppp/ && "modem" ||
+ (detect_devices::is_wireless_interface($interface->{DEVICE}) || exists $interface->{WIRELESS_MODE}) && "wifi" ||
+ detect_devices::is_lan_interface($interface->{DEVICE}) &&
+ ($o_module && member($o_module, list_modules::category2modules('network/gigabit')) ? "ethernet_gigabit" : "ethernet") ||
+ "unknown";
+}
+
+sub get_interface_description {
+ my ($net, $interface_name) = @_;
+ my $type = get_interface_type($net->{ifcfg}{$interface_name});
+ #- FIXME: find interface description (from PCI/USB data) and translate
+ $type eq 'adsl' ? "DSL: $interface_name" :
+ $type eq 'isdn' ? "ISDN: $interface_name" :
+ $type eq 'modem' ? "Modem: $interface_name" :
+ $type eq 'wifi' ? "WiFi: $interface_name" :
+ member($type, qw(ethernet_gigabit ethernet)) ? "Ethernet: $interface_name" :
+ $interface_name;
+}
+
+sub get_default_metric {
+ my ($type) = @_;
+ my @known_types = ("ethernet_gigabit", "ethernet", "adsl", "wifi", "isdn", "modem", "unknown");
+ my $idx;
+ eval { $idx = find_index { $type eq $_ } @known_types };
+ $idx = @known_types if $@;
+ $idx * 10;
+}
+
+sub get_interface_ip_address {
+ my ($net, $interface) = @_;
+ `/sbin/ip addr show dev $interface` =~ /^\s*inet\s+([\d.]+).*\s+$interface$/m && $1 ||
+ $net->{ifcfg}{$interface}{IPADDR};
+}
+
+sub get_interface_ptp_address {
+ my ($interface) = @_;
+ my ($flags, $_link, $addrs) = `/sbin/ip addr show dev $interface`;
+ $flags =~ /\bPOINTOPOINT\b/ or return;
+ my ($peer) = $addrs =~ /peer\s+([\d.]+)/;
+ return $peer if $peer;
+ my ($addr) = $addrs =~ /inet\s+([\d.]+)/;
+ return $addr if $addr;
+}
+
+sub host_hex_to_dotted {
+ my ($address) = @_;
+ inet_ntoa(pack('N', unpack('L', pack('H8', $address))));
+}
+
+sub get_routes() {
+ my %routes;
+ foreach (cat_("/proc/net/route")) {
+ if (/^(\S+)\s+([0-9A-F]+)\s+([0-9A-F]+)\s+[0-9A-F]+\s+\d+\s+\d+\s+(\d+)\s+([0-9A-F]+)/) {
+ if (defined $3) { $routes{$1}{gateway} = hex($3) ? host_hex_to_dotted($3) : $routes{$1}{network} }
+ if (defined $2) { $routes{$1}{network} = host_hex_to_dotted($2) }
+ if (defined $4) { $routes{$1}{metric} = $4 }
+ }
+ }
+ $routes{$_}{gateway} ||= get_interface_ptp_address($_) foreach keys %routes;
+ #- TODO: handle IPv6 with /proc/net/ipv6_route
+ \%routes;
+}
+
+1;
diff --git a/lib/network/vpn.pm b/lib/network/vpn.pm
new file mode 100644
index 0000000..4a5afbc
--- /dev/null
+++ b/lib/network/vpn.pm
@@ -0,0 +1,191 @@
+package network::vpn;
+
+=head1 NAME
+
+network::vpn - VPN connection abstract class
+
+=cut
+
+use strict;
+use common;
+
+my $vpn_d = "/etc/sysconfig/network-scripts/vpn.d";
+
+=head1 CLASS METHODS
+
+=head2 Generic class methods
+
+=over
+
+=item list_types
+
+List supported VPN types
+
+=cut
+
+sub list_types {
+ common::load_modules_from_base(__PACKAGE__);
+}
+
+=item get_configured_connections
+
+Return list of configured connections for this class
+
+=cut
+
+sub get_configured_connections {
+ my ($class) = @_;
+ map { if_(/^(.*).conf$/, $class->new($1)) } all($::prefix . $vpn_d . '/' . $class->get_type);
+}
+
+=item new(NAME)
+
+Create a new VPN connection object named NAME
+
+=cut
+
+sub new {
+ my ($class, $name) = @_;
+ bless {
+ name => $name,
+ }, $class;
+}
+
+=back
+
+=head2 Pure virtual class methods
+
+=over
+
+=item get_type
+
+Return VPN type (preferably one lowercase word)
+
+=item get_description
+
+Return description of the VPN type
+
+=item get_packages
+
+List package required for configuration
+
+=back
+
+=head1 INSTANCE METHODS
+
+=head2 Generic instance methods
+
+=over
+
+=item get_name
+
+Return name of the VPN connection
+
+=cut
+
+sub get_name {
+ my ($connection) = @_;
+ $connection->{name};
+}
+
+=item get_label
+
+Return label of the VPN connection
+
+=cut
+
+sub get_label {
+ my ($connection) = @_;
+ sprintf("%s (%s)", $connection->get_name, $connection->get_type);
+}
+
+=item get_config_path
+
+Get configuration file path
+
+=cut
+
+sub get_config_path {
+ my ($connection) = @_;
+ $::prefix . $vpn_d . '/' . $connection->get_type . '/' . $connection->get_name . '.conf';
+}
+
+sub _run {
+ my ($connection, $action, @args) = @_;
+ my @command = ('vpn-' . $action, $connection->get_type, $connection->get_name, @args);
+ @command = common::wrap_command_for_root(@command) if $>;
+ require run_program;
+ run_program::rooted($::prefix, , @command);
+}
+
+=item start($o_in)
+
+Start the VPN connection
+
+$o_in is an interactive object used to interact with the user,
+used if some interactive username/passwords are required.
+If not specified, there is no user interaction.
+
+=cut
+
+sub start {
+ my ($connection, $_o_in) = @_;
+ $connection->_run('start');
+}
+
+=item stop
+
+Stop the VPN connection
+
+=cut
+
+sub stop {
+ my ($connection) = @_;
+ $connection->_run('stop');
+}
+
+=item is_started
+
+Returns true if the VPN connection is started
+
+=cut
+
+sub is_started {
+ my ($connection) = @_;
+ my $pid = chomp_(cat_($::prefix . '/var/run/' . $connection->get_type . '-' . $connection->get_name . '.pid'));
+ $pid && -e '/proc/' . $pid;
+}
+
+=back
+
+=head2 Pure virtual instance methods
+
+=over
+
+=item read_config
+
+Read configuration from the file returned by get_config_path()
+
+=item write_config
+
+Write configuration to the file returned by get_config_path()
+
+=item get_settings
+
+Return an array ref of interactive settings
+
+=back
+
+=head2 Optional instance methods
+
+=over
+
+=item prepare
+
+Run commands or services that are required for the VPN type
+
+=back
+
+=cut
+
+1;
diff --git a/lib/network/vpn/openvpn.pm b/lib/network/vpn/openvpn.pm
new file mode 100644
index 0000000..68e1b3f
--- /dev/null
+++ b/lib/network/vpn/openvpn.pm
@@ -0,0 +1,409 @@
+package network::vpn::openvpn;
+
+use base qw(network::vpn);
+
+use strict;
+use common;
+
+sub get_type { 'openvpn' }
+sub get_description { "OpenVPN" }
+sub get_packages { 'openvpn', if_(supports_pkcs11(), qw(openct opensc pcsc-lite)) }
+
+my $pkcs11_tokens;
+
+sub prepare {
+ require services;
+ if (supports_pkcs11()) {
+ #- don't fail if SmartCard daemons can't start, it's not mandatory
+ services::start_not_running_service($_) foreach qw(openct pcscd);
+ cache_pkcs11_tokens();
+ }
+ 1;
+}
+
+sub read_config {
+ my ($connection) = @_;
+ my ($pkcs11_slot, $pkcs11_id);
+ foreach (cat_($connection->get_config_path)) {
+ /^\s*proto\s+tcp/ and $connection->{tcp} = 1;
+ /^\s*dev\s+([[:alpha:]]+)(\d*)/ and ($connection->{dev_type}, $connection->{dev_number}) = ($1, $2);
+ if (/^\s*remote\s+(\S+)(?:\s+(\w+))?/) {
+ $connection->{gateway} = $1;
+ $connection->{port} = $2;
+ }
+ if (/^\s*tls-auth\s+(\S+)(?:\s+(\d+))?/) {
+ $connection->{'tls-auth'} = $1;
+ $connection->{key_direction} = $2;
+ }
+ foreach my $type (qw(ca cert key pkcs12 secret)) {
+ /^\s*$type\s+(.+)/ and $connection->{$type . '_file'} = $1;
+ }
+ /^\s*pkcs11-slot\s+(.+)/ and $pkcs11_slot = $1;
+ /^\s*pkcs11-id\s+(.+)/ and $pkcs11_id = $1;
+ /^\s*ns-cert-type\s+server/ and $connection->{check_server} = 1;
+ /^\s*auth-user-pass/ and $connection->{'auth-user-pass'} = 1;
+ if (/^\s*ifconfig\s+(\S+)\s+(\S+)/) {
+ $connection->{local_ip} = $1;
+ $connection->{remote_ip} = $2;
+ $connection->{addressing} = 'manual';
+ }
+ /^\s*cipher\s+(.+)/ and $connection->{cipher} = $1;
+ /^\s*keysize\s+(.+)/ and $connection->{keysize} = $1;
+ }
+ if (exists $connection->{secret_file}) {
+ $connection->{type} = 'static';
+ $connection->{key} = delete $connection->{secret_file};
+ } else {
+ $connection->{type} = 'pki';
+ $connection->{key} = delete $connection->{key_file};
+ }
+ if (defined $pkcs11_slot && defined $pkcs11_id) {
+ my $tokens = $connection->get_pkcs11_tokens('no_cache');
+ $connection->{pkcs11_object} = find { $_->{slot} eq $pkcs11_slot && $_->{id} eq $pkcs11_id } @{$tokens->{objects}};
+ $connection->{pkcs11_object} ||= {};
+ }
+}
+
+sub write_config {
+ my ($connection) = @_;
+ my $file = $connection->get_config_path;
+ unless (-e $file) {
+ mkdir_p(dirname($file));
+ cp_f("/usr/share/openvpn/sample-config-files/client.conf", $file);
+ }
+
+ delete $connection->{keysize} if !$connection->{cipher};
+ delete $connection->{ca_file} if $connection->{pkcs12_file};
+
+ if ($connection->{type} eq 'static') {
+ $connection->{secret_file} = delete $connection->{key};
+ delete $connection->{ca_file};
+ delete $connection->{cert_file};
+ delete $connection->{key_file};
+ } else {
+ $connection->{key_file} = delete $connection->{key};
+ delete $connection->{secret_file};
+ }
+
+ my @config = $connection->build_config;
+ substInFile {
+ foreach my $conf (@config) {
+ if (/^;?$conf->{key}\b/) {
+ if ($conf->{comment}) {
+ $_ = ";$_" unless /^;/;
+ } else {
+ $_ = "$conf->{key} $conf->{value}\n";
+ $conf->{comment} = 1;
+ }
+ last;
+ }
+ }
+ $_ .= join('', map { if_(!$_->{comment}, "$_->{key} $_->{value}\n") } @config) if eof;
+ } $file;
+}
+
+sub get_key_settings {
+ my ($connection) = @_;
+ my %ciphers = get_ciphers();
+ my @types = (
+ pki => N("X509 Public Key Infrastructure"),
+ static => N("Static Key"),
+ );
+ my $pkcs11_separator = '/';
+ my $tokens = $connection->get_pkcs11_tokens;
+ my %types = @types;
+ [
+ {
+ label => N("Type"),
+ val => \$connection->{type},
+ list => first(list2kv(@types)),
+ format => sub { $types{$_[0]} },
+ },
+ (supports_pkcs11() ? {
+ label => "PKCS #11 token",
+ type => 'list',
+ list => [ undef, @{$tokens->{objects}} ],
+ format => sub { $_[0] ? join($pkcs11_separator,
+ $tokens->{slots}{$_[0]{slot}}{label} || $_[0]{slot},
+ $_[0]{label} || $_[0]{id})
+ : N("None") },
+ val => \$connection->{pkcs11_object},
+ separator => $pkcs11_separator,
+ allow_empty_list => 1,
+ disabled => sub { $connection->{type} ne 'pki' || $connection->{cert_file} || $connection->{key_file} || $connection->{pkcs12_file} },
+ } : ()),
+ {
+ label => "PKCS #12",
+ type => 'file',
+ val => \$connection->{pkcs12_file},
+ disabled => sub { $connection->{type} ne 'pki' || $connection->{cert_file} || $connection->{key_file} || $connection->{pkcs11_object} },
+ },
+ {
+ label =>
+ #-PO: please don't translate the CA acronym
+ N("Certificate Authority (CA)"),
+ type => 'file',
+ val => \$connection->{ca_file},
+ disabled => sub { $connection->{type} ne 'pki' || $connection->{pkcs12_file} },
+ },
+ {
+ label => N("Certificate"),
+ type => 'file',
+ val => \$connection->{cert_file},
+ disabled => sub { $connection->{type} ne 'pki' || $connection->{pkcs11_object} || $connection->{pkcs12_file} },
+ },
+ {
+ label => N("Key"),
+ type => 'file',
+ val => \$connection->{key},
+ disabled => sub { $connection->{type} eq 'pki' && ($connection->{pkcs11_object} || $connection->{pkcs12_file}) },
+ },
+ {
+ label => N("TLS control channel key"),
+ type => 'file',
+ val => \$connection->{'tls-auth'},
+ disabled => sub { $connection->{type} ne 'pki' },
+ advanced => 1,
+ },
+ {
+ label => N("Key direction"),
+ type => 'list',
+ val => \$connection->{key_direction},
+ list => [ undef, 0, 1 ],
+ format => sub { defined($_[0]) ? $_[0] : N("None") },
+ advanced => 1,
+ },
+ {
+ text => N("Authenticate using username and password"),
+ type => 'bool',
+ val => \$connection->{'auth-user-pass'},
+ advanced => 1,
+ },
+ {
+ text => N("Check server certificate"),
+ type => 'bool',
+ val => \$connection->{check_server},
+ advanced => 1,
+ },
+ {
+ label => N("Cipher algorithm"),
+ type => 'list',
+ val => \$connection->{cipher},
+ list => [ '', keys %ciphers ],
+ format => sub { exists $ciphers{$_[0]} ? $ciphers{$_[0]} : N("Default") },
+ advanced => 1,
+ },
+ {
+ label => N("Size of cipher key"),
+ val => \$connection->{keysize},
+ advanced => 1,
+ disabled => sub { !$connection->{cipher} || $connection->{cipher} eq 'none' },
+ },
+ ];
+}
+
+sub get_settings {
+ my ($connection) = @_;
+ my @addressing = (
+ automatic => N("Get from server"),
+ manual => N("Manual configuration"),
+ );
+ my %addressing = @addressing;
+ [
+ {
+ label => N("Gateway"),
+ val => \$connection->{gateway},
+ },
+ {
+ label => N("Gateway port"),
+ val => \$connection->{port},
+ advanced => 1,
+ },
+ {
+ label => N("IP address"),
+ val => \$connection->{addressing},
+ list => first(list2kv(@addressing)),
+ format => sub { $addressing{$_[0]} },
+ },
+ {
+ label => N("Local IP address"),
+ val => \$connection->{local_ip},
+ disabled => sub { $connection->{addressing} ne 'manual' },
+ },
+ {
+ label => N("Remote IP address"),
+ val => \$connection->{remote_ip},
+ disabled => sub { $connection->{addressing} ne 'manual' },
+ },
+ {
+ text => N("Use TCP protocol"),
+ type => 'bool',
+ val => \$connection->{tcp},
+ advanced => 1,
+ },
+ {
+ label => N("Virtual network device type"),
+ type => 'list',
+ list => [ 'tun', 'tap' ],
+ val => \$connection->{dev_type},
+ advanced => 1,
+ },
+ {
+ label => N("Virtual network device number (optional)"),
+ val => \$connection->{dev_number},
+ advanced => 1,
+ },
+ ];
+}
+
+my $lib = arch() =~ /x86_64/ ? "lib64" : "lib";
+my $openvpn_default_pkcs11_provider = find { -e $_ } (
+ "/usr/local/$lib/libetpkcs11.so",
+ "/usr/$lib/opensc-pkcs11.so",
+);
+
+my $supports_pkcs11;
+sub supports_pkcs11 {
+ if (!defined $supports_pkcs11) {
+ require run_program;
+ $supports_pkcs11 = to_bool(run_program::rooted($::prefix, '/usr/sbin/openvpn', '--show-pkcs11-slots', ''));
+ }
+ $supports_pkcs11;
+}
+
+sub get_pkcs11_tokens {
+ my ($_class, $o_no_cache) = @_;
+ cache_pkcs11_tokens() if !defined $pkcs11_tokens && !$o_no_cache;
+ $pkcs11_tokens;
+}
+
+sub cache_pkcs11_tokens {
+ $pkcs11_tokens = { slots => {}, objects => [] };
+ my $slot_id;
+ foreach (run_program::rooted_get_stdout($::prefix, '/usr/bin/pkcs11-tool', '--module', $openvpn_default_pkcs11_provider, '-L')) {
+ if (/^Slot\s+(\d+)\s+(.+)$/) {
+ $slot_id = $2 ne '(empty)' ? $1 : undef;
+ $pkcs11_tokens->{slots}{$slot_id}{name} = $2 if defined $slot_id;
+ } elsif (/^\s+token\s+label:\s+(.+)$/) {
+ $pkcs11_tokens->{slots}{$slot_id}{label} = $1 if defined $slot_id;
+ } elsif (/^\s+flags:\s*(.*)/) {
+ my @flags = split(/\s*,\s*/, $1);
+ if (defined $slot_id && !member("token present", @flags)) {
+ delete $pkcs11_tokens->{slots}{$slot_id};
+ undef $slot_id;
+ }
+ }
+ }
+ foreach $slot_id (keys %{$pkcs11_tokens->{slots}}) {
+ my ($type, $label);
+ my @stdout; #- do rooted_get_stdout manually because pkcs11-tool may exit with non-zero code with proprietary modules
+ run_program::rooted($::prefix, '/usr/bin/pkcs11-tool', '>', \@stdout, '--module', $openvpn_default_pkcs11_provider, '-O', '--slot', $slot_id);
+ foreach (@stdout) {
+ if (/^(\S.*?)\s+Object/) {
+ $type = $1;
+ undef $label;
+ } elsif (/^\s+label:\s+(.+)$/) {
+ $label = $1;
+ } elsif (/^\s+ID:\s+(.+)$/ && $type eq 'Public Key') {
+ push @{$pkcs11_tokens->{objects}}, { id => $1, label => $label, slot => $slot_id };
+ }
+ }
+ }
+}
+
+sub build_config {
+ my ($connection) = @_;
+ (
+ { key => 'client', comment => to_bool($connection->{secret_file}) },
+ { key => 'proto', $connection->{tcp} ? (value => 'tcp') : (comment => 1) },
+ { key => 'dev', value => $connection->{dev_type} . $connection->{dev_number} },
+ { key => 'remote', value => join(' ', $connection->{gateway}, if_($connection->{port}, $connection->{port})) },
+ (map { +{ key => $_, $connection->{$_ . '_file'} ? (value => $connection->{$_ . '_file'}) : (comment => 1) } } qw(ca cert key pkcs12 secret)),
+ { key => 'pkcs11-providers', $connection->{pkcs11_object} ? (value => $openvpn_default_pkcs11_provider) : (comment => 1) },
+ { key => 'pkcs11-slot-type', $connection->{pkcs11_object} ? (value => 'id') : (comment => 1) },
+ { key => 'pkcs11-slot', $connection->{pkcs11_object} ? (value => $connection->{pkcs11_object}{slot}) : (comment => 1) },
+ { key => 'pkcs11-id-type', $connection->{pkcs11_object} ? (value => 'id') : (comment => 1) },
+ { key => 'pkcs11-id', $connection->{pkcs11_object} ? (value => $connection->{pkcs11_object}{id}) : (comment => 1) },
+ { key => 'tls-auth', $connection->{'tls-auth'} ? (value => join(' ', $connection->{'tls-auth'}, if_($connection->{key_direction}, $connection->{key_direction}))) : (comment => 1) },
+ { key => 'ns-cert-type', $connection->{check_server} ? (value => 'server') : (comment => 1) },
+ { key => 'auth-user-pass', comment => !$connection->{'auth-user-pass'} },
+ { key => 'ifconfig', $connection->{addressing} eq 'manual' ?
+ (value => join(' ', $connection->{local_ip}, $connection->{remote_ip})) : (comment => 1) },
+ { key => 'cipher', $connection->{cipher} ? (value => $connection->{cipher}) : (comment => 1) },
+ { key => 'keysize', $connection->{keysize} ? (value => $connection->{keysize}) : (comment => 1) },
+ );
+}
+
+sub get_ciphers() {
+ my @ciphers = chomp_(`/usr/sbin/openvpn --show-ciphers`);
+ #- drop header
+ shift @ciphers while $ciphers[0] =~ /^\S/;
+ none => N("None"), map { if_($_, first(split(' ', $_)), $_) } @ciphers;
+}
+
+sub start {
+ my ($connection, $o_in) = @_;
+ $connection->read_config if keys %$connection <= 1;
+ my %interactive_passwords = if_($o_in, (
+ if_($connection->{'auth-user-pass'}, 'Auth' => 1),
+ if_($connection->{pkcs11_object}, 'Token' => 1),
+ ));
+ my $port = 2222;
+ my $started = $connection->_run('start',
+ if_(%interactive_passwords,
+ '--management', "127.0.0.1", $port,
+ '--management-query-passwords',
+ ));
+ $started && (!%interactive_passwords || $connection->ask_passwords($o_in, $port, \%interactive_passwords));
+}
+
+sub ask_passwords {
+ my ($_connection, $in, $port, $interactive_passwords) = @_;
+ require Net::Telnet;
+ my $t = new Net::Telnet;
+ $t->open(host => "localhost", port => $port, errmode => "return");
+ my $wait;
+ while (1) {
+ $wait ||= $in->wait_message(N("VPN connection"), N("Starting connection.."));
+ my ($_pre, $match) = $t->waitfor(string => ">PASSWORD:", string => ">NEED-OK:", errmode => "return",
+ #- don't quit if all interactive passwords have been entered
+ #- in case some passwords are incorrect
+ #- though, use a smaller timeout
+ timeout => (%$interactive_passwords ? 20 : 5));
+ if (!defined $match) {
+ my $msg = $t->errmsg;
+ #- no more interactive password is required, success
+ $t->close, return 1 if $msg =~ /timed-out/ && !%$interactive_passwords;
+ $t->close, return; #- potential failure
+ } elsif ($match eq ">NEED-OK:") {
+ my ($type, $msg) = $t->getline =~ /'(.*)'.* MSG:/;
+ undef $wait;
+ my $ret = $in->ask_okcancel(N("VPN connection"), $type eq 'token-insertion-request' ?
+ N("Please insert your token") :
+ $msg);
+ $t->print(qq(needok "$type" ) . ($ret ? "ok" : "cancel"));
+ $t->close, return if !$ret;
+ } elsif ($match eq ">PASSWORD:") {
+ my ($full_type) = $t->getline =~ /'(.*)'/;
+ #- assume type is "Auth" if not token
+ my $type = $full_type =~ /\btoken$/ ? 'Token' : 'Auth';
+ my ($username, $password);
+ undef $wait;
+ my $ret = $in->ask_from(N("VPN connection"), '', $type eq 'Token' ? [
+ { label => N("PIN number"), val => \$password, hidden => 1 }
+ ] : [
+ { label => N("Account Login (user name)"), val => \$username },
+ { label => N("Account Password"), val => \$password, hidden => 1 },
+ ]);
+ if ($ret) {
+ delete $interactive_passwords->{$type};
+ $t->print(qq(username "$full_type" "$username")) if $username;
+ $t->print(qq(password "$full_type" "$password"));
+ } else {
+ $t->close, return;
+ }
+ }
+ }
+}
+
+1;
diff --git a/lib/network/vpn/vpnc.pm b/lib/network/vpn/vpnc.pm
new file mode 100644
index 0000000..c7a87c7
--- /dev/null
+++ b/lib/network/vpn/vpnc.pm
@@ -0,0 +1,74 @@
+package network::vpn::vpnc;
+
+use base qw(network::vpn);
+
+use strict;
+use common;
+
+sub get_type { 'vpnc' }
+sub get_description { N("Cisco VPN Concentrator") }
+sub get_packages { 'vpnc' }
+
+sub read_config {
+ my ($connection) = @_;
+ my @fields = group_by2(list_fields($connection));
+ foreach (cat_($connection->get_config_path)) {
+ foreach my $field (@fields) {
+ # all strings start exactly one space after the keyword string
+ /^$field->[0] (.*)/ and ${$field->[1]{val}} = $1;
+ }
+ }
+}
+
+sub write_config {
+ my ($connection) = @_;
+ output_with_perm($connection->get_config_path, 0600, map {
+ if_(${$_->[1]{val}}, $_->[0], ' ', ${$_->[1]{val}}, "\n");
+ } group_by2(list_fields($connection)));
+}
+
+sub get_settings {
+ my ($connection) = @_;
+ second(list2kv(list_fields($connection)));
+}
+
+sub list_fields {
+ my ($connection) = @_;
+ (
+ 'IPSec gateway' => {
+ label => N("Gateway"),
+ val => \$connection->{gateway},
+ },
+ 'IPSec ID' => {
+ label => N("Group name"),
+ val => \$connection->{id},
+ },
+ 'IPSec secret' => {
+ label => N("Group secret"),
+ val => \$connection->{secret},
+ hidden => 1,
+ },
+ 'Xauth username' => {
+ label => N("Username"),
+ val => \$connection->{username},
+ },
+ 'Xauth password' => {
+ label => N("Password"),
+ val => \$connection->{password},
+ hidden => 1,
+ },
+ 'NAT Traversal Mode' => {
+ label => N("NAT Mode"),
+ list => [ '', qw(natt none force-natt cisco-udp) ],
+ val => \$connection->{udp},
+ advanced => 1,
+ },
+ 'Cisco UDP Encapsulation Port' => {
+ label => N("Use specific UDP port"),
+ val => \$connection->{udp_port},
+ advanced => 1,
+ },
+ );
+}
+
+1;