diff options
Diffstat (limited to 'bin')
-rw-r--r-- | bin/.perl_checker | 1 | ||||
-rwxr-xr-x | bin/drakconnect | 155 | ||||
-rwxr-xr-x | bin/drakfirewall | 4 | ||||
-rwxr-xr-x | bin/drakgw | 38 | ||||
-rw-r--r-- | bin/drakhosts | 35 | ||||
-rw-r--r-- | bin/drakids | 67 | ||||
-rwxr-xr-x | bin/drakinvictus | 151 | ||||
-rwxr-xr-x | bin/draknetcenter | 132 | ||||
-rwxr-xr-x | bin/draknetprofile | 153 | ||||
-rw-r--r-- | bin/draknfs | 190 | ||||
-rwxr-xr-x | bin/drakproxy | 13 | ||||
-rwxr-xr-x | bin/drakroam | 405 | ||||
-rwxr-xr-x | bin/draksambashare | 322 | ||||
-rw-r--r-- | bin/drakvpn | 1139 | ||||
-rwxr-xr-x | bin/drakvpn-old | 847 | ||||
-rw-r--r-- | bin/net_applet | 489 | ||||
-rwxr-xr-x | bin/net_monitor | 162 |
17 files changed, 2368 insertions, 1935 deletions
diff --git a/bin/.perl_checker b/bin/.perl_checker new file mode 100644 index 0000000..202e053 --- /dev/null +++ b/bin/.perl_checker @@ -0,0 +1 @@ +Basedir .. diff --git a/bin/drakconnect b/bin/drakconnect index 64b300e..ece74c5 100755 --- a/bin/drakconnect +++ b/bin/drakconnect @@ -2,7 +2,7 @@ # DrakConnect $Id$ -# Copyright (C) 1999-2005 Mandriva +# Copyright (C) 1999-2006 Mandriva # Damien "Dam's" Krotkine # Damien "poulpy" Chaumette # Thierry Vignaud <tvignaud@mandriva.com> @@ -25,28 +25,33 @@ use strict; use lib qw(/usr/lib/libDrakX); +# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX) +BEGIN { unshift @::textdomains, 'drakx-net' } use standalone; #- warning, standalone must be loaded very first, for 'explanations' use interactive; use common; +use run_program; use network::netconnect; -use network::ethernet; +use network::connection::ethernet; use network::tools; use network::modem; use network::network; use detect_devices; use c; use modules; -use network::isdn; use network::adsl; +use network::connection::isdn; use network::test; use POSIX ":sys_wait_h"; $ugtk2::wm_icon = "drakconnect"; my $in = 'interactive'->vnew('su'); if ($in->isa('interactive::gtk')) { + require mygtk2; require ugtk2; ugtk2->import(qw(:create :dialogs :helpers :wrappers)); + mygtk2->import(qw(gtknew)); } my $net = {}; @@ -73,11 +78,10 @@ add_intf(); old: my @all_cards; -my $window1 = ugtk2->new('drakconnect'); +my $window1 = ugtk2->new(N("Network configuration (%d adapters)", scalar @all_cards)); $window1->{rwindow}->signal_connect(delete_event => sub { ugtk2->exit(0) }); unless ($::isEmbedded) { $window1->{rwindow}->set_position('center'); - $window1->{rwindow}->set_title(N("Network configuration (%d adapters)", scalar @all_cards)); $window1->{rwindow}->set_size_request(-1, -1); } $window1->{rwindow}->set_border_width(10); @@ -86,7 +90,7 @@ my $button_apply; my $hostname = chomp_(`hostname`); -my $int_label = Gtk2::Label->new($net->{type} eq 'lan' ? N("Gateway:") : N("Interface:")); +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 $isconnected = -1; @@ -121,8 +125,8 @@ my ($label_host, $int_state); $window1->{window}->add( - gtkpack_(Gtk2::VBox->new(0,10), - 0, gtkpack(Gtk2::HBox->new, + gtkpack__(Gtk2::VBox->new(0,10), + gtkpack(Gtk2::HBox->new, Gtk2::Label->new(N("Hostname: ")), $label_host = Gtk2::Label->new($hostname), gtksignal_connect(Gtk2::Button->new(N("Configure hostname...")), @@ -139,7 +143,7 @@ $window1->{window}->add( } ), ), - 1, gtkadd(gtkcreate_frame(N("LAN configuration")), + gtkadd(gtkcreate_frame(N("LAN configuration")), gtkpack_(gtkset_border_width(Gtk2::VBox->new(0,0), 5), 0, $list, 0, Gtk2::HBox->new(0,0), @@ -149,9 +153,9 @@ $window1->{window}->add( ), ) ), - 0, gtkpack(Gtk2::HButtonBox->new, + gtkpack(Gtk2::HButtonBox->new, gtksignal_connect(Gtk2::Button->new(N("Help")), clicked => sub { - exec("drakhelp --id internet-connection") unless fork() }), + run_program::raw({ detach => 1 }, 'drakhelp', '--id', 'internet-connection') }), $button_apply = gtksignal_connect(gtkset_sensitive(Gtk2::Button->new(N("Apply")), 0), clicked => \&apply), gtksignal_connect(Gtk2::Button->new(N("Cancel")), clicked => \&quit_global), @@ -192,8 +196,8 @@ sub manage() { $notebook->set_property('show-tabs', 0); $notebook->set_property('show-border', 0); - @all_cards = network::ethernet::get_eth_cards($modules_conf); - my %names = network::ethernet::get_eth_cards_names(@all_cards); + @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} = { @@ -212,7 +216,7 @@ sub manage() { $window->{rwindow}->add(gtkpack_(Gtk2::VBox->new, 0, gtkpack__(Gtk2::HBox->new, - Gtk2::Label->new(N("Device selected")), + gtknew('Label', text => N("Device: "), alignment => [ 0, 0 ]), $interface_menu = gtksignal_connect(Gtk2::ComboBox->new_text, changed => sub { $selected = $interface_menu->get_text; @@ -233,7 +237,7 @@ sub manage() { }, }, undef, undef, '', - [ N("Help"), sub { exec("drakhelp --id internet-connection") unless fork() } ], + [ N("Help"), sub { run_program::raw({ detach => 1 }, 'drakhelp', '--id', 'internet-connection') } ], [ N("Apply"), sub { save($p, $apply_button) }, 0, 1 ], ), ), @@ -266,7 +270,7 @@ sub build_tree { network::adsl::adsl_probe_info($net); $intf->{save} = sub { $net->{type} = 'adsl'; - network::adsl::adsl_conf_backend($in, $modules_conf, $net); + network::adsl::adsl_conf_backend($in, $net); }; } elsif ($interface eq 'modem') { @@ -276,8 +280,8 @@ sub build_tree { } elsif ($interface eq 'isdn') { $intf->{pages} = { 'TCP/IP' => 1, 'Account' => 1, 'Modem' => 1, 'Options' => 1 }; - network::isdn::read_config($intf); - $intf->{save} = sub { network::isdn::write_config($in, $intf) }; + network::connection::isdn::read_config($intf); + $intf->{save} = sub { network::connection::isdn::apply_config($in, $intf) }; } else { #- ethernet is default @@ -291,13 +295,14 @@ sub build_notebook { 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'} = Gtk2::HBox->new, - gtkadd(gtkcreate_frame(N("IP configuration")), - gtkpack_(gtkset_border_width(Gtk2::VBox->new(0,10), 5), + gtkpack__($gui->{sheet}{'TCP/IP'} = gtkset_border_width(Gtk2::VBox->new(0,10), 5), + gtknew('Title2', label => N("IP configuration")), if_($is_ethernet, - 0, gtkpack__(Gtk2::HBox->new, - Gtk2::Label->new(N("Protocol")), + 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}; @@ -312,39 +317,34 @@ sub build_notebook { ), ), ), - 0, gtkpack(Gtk2::VBox->new(1,0), - gtkpack__(Gtk2::HBox->new, Gtk2::Label->new(N("IP address"))), - gtkpack__(Gtk2::HBox->new, gtksignal_connect($gui->{intf}{IPADDR} = Gtk2::Entry->new, - key_press_event => $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), ), - 0, gtkpack(Gtk2::VBox->new(1,0), - gtkpack__(Gtk2::HBox->new, Gtk2::Label->new(N("Netmask"))), - gtkpack__(Gtk2::HBox->new, gtksignal_connect($gui->{intf}{NETMASK} = 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, - 0, gtkpack(Gtk2::VBox->new(1,0), - gtkpack__(Gtk2::HBox->new, Gtk2::Label->new(N("Gateway"))), - gtkpack__(Gtk2::HBox->new, gtksignal_connect($gui->{network}{GATEWAY} = Gtk2::Entry->new, - key_press_event => $apply)), + gtkpack(Gtk2::HBox->new(1,0), + gtknew('Label_Left', text => N("Gateway")), + gtksignal_connect($gui->{network}{GATEWAY} = Gtk2::Entry->new, + key_press_event => $apply), ), ), - ), - ), - gtkpack_(Gtk2::VBox->new, - 1, gtkadd(gtkcreate_frame(N("DNS servers")), - gtkpack(Gtk2::VBox->new(0,0), - Gtk2::Label->new($intf->{dns1} || $net->{resolv}{dnsServer}), - if_($intf->{dns2} || $net->{resolv}{dnsServer2}, - Gtk2::Label->new($intf->{dns2} || $net->{resolv}{dnsServer2})), - if_($intf->{dns3} || $net->{resolv}{dnsServer3}, - Gtk2::Label->new($intf->{dns3} || $net->{resolv}{dnsServer3}))), - ), - 1, gtkadd(gtkcreate_frame(N("Search Domain")), - Gtk2::Label->new($intf->{domain} || $net->{resolv}{DOMAINNAME} || 'none'), - ), + 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}; @@ -365,18 +365,18 @@ sub build_notebook { 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, - Gtk2::Label->new(N("DHCP client")), - gtksignal_connect($gui->{intf}{DHCP_CLIENT} = Gtk2::ComboBox->new_with_strings(\@network::ethernet::dhcp_clients, - $intf->{DHCP_CLIENT} || $network::ethernet::dhcp_clients[0]), + 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 address")), toggled => $apply), - gtkpack__(Gtk2::HBox->new, - Gtk2::Label->new(N("DHCP host name")), + 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, - Gtk2::Label->new(N("DHCP timeout (in seconds)")), + 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), @@ -392,6 +392,8 @@ sub build_notebook { $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), @@ -434,7 +436,7 @@ sub build_notebook { if_($is_ethernet, map { ($gui->{intf_bool}{$_->[0]} = gtksignal_connect(Gtk2::CheckButton->new($_->[1]), toggled => $apply)); - } ([ "HWADDR", N("Track network card id (useful for laptops)") ], + } ( [ "MII_NOT_SUPPORTED", N("Network Hotplugging") ], ), ), @@ -456,8 +458,8 @@ sub build_notebook { key_press_event => $apply), ), ), - gtkpack__(Gtk2::HBox->new(0,5), - Gtk2::Label->new(N("Metric")), + 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)), @@ -468,7 +470,6 @@ sub build_notebook { $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); - $gui->{intf_bool}{HWADDR}->set_active($intf->{HWADDR}); } if ($intf->{pages}{Account}) { @@ -576,7 +577,7 @@ sub build_notebook { if ($intf->{pages}{Information}) { my ($info) = $gui->{description} ? - find { $_->{description} eq $gui->{description} } detect_devices::probeall : network::ethernet::mapIntfToDevice($interface_name); + 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]; @@ -666,7 +667,6 @@ sub save_notebook { $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); - $gui->{intf_bool}{HWADDR} and (bool2yesno($gui->{intf_bool}{HWADDR}->get_active) eq 'yes' ? ($intf->{HWADDR} = 'yes') : delete $intf->{HWADDR}); if (my $proto = $gui->{intf}{BOOTPROTO}) { $intf->{BOOTPROTO} = { reverse %{$proto->{protocols}} }->{$proto->get_text}; @@ -681,6 +681,10 @@ sub save_notebook { 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; @@ -691,6 +695,7 @@ sub save_notebook { sub add_intf() { $::isWizard = 1; network::netconnect::safe_main($net, $in, $modules_conf); + $modules_conf->write; $in->exit(0); } @@ -700,8 +705,8 @@ sub del_intf() { $in->ask_warn(N("Error"), N("No ethernet network adapter has been detected on your system. Please run the hardware configuration tool.")); $in->exit(0); } - @all_cards = network::ethernet::get_eth_cards($modules_conf); - my %ethernet_names = network::ethernet::get_eth_cards_names(@all_cards); + @all_cards = network::connection::ethernet::get_eth_cards($modules_conf); + my %ethernet_names = network::connection::ethernet::get_eth_cards_names(@all_cards); require wizards; my $wiz = wizards->new( { @@ -736,6 +741,7 @@ sub del_intf() { } }; $failure = $@; + network::network::reload_net_applet(); return "end"; }, }, @@ -772,7 +778,7 @@ my %intf; sub update_list { my ($modules_conf) = @_; - @all_cards = network::ethernet::get_eth_cards($modules_conf); + @all_cards = network::connection::ethernet::get_eth_cards($modules_conf); my %new_intf = map { @$_ } @all_cards; my @new_intf = sort keys %new_intf; foreach my $interface (difference2(\@new_intf, [ keys %intf ])) { @@ -913,7 +919,7 @@ Configure them first by clicking on 'Configure'"))); if (-e "/etc/sysconfig/network-scripts/ifcfg-$interface") { $widget_temp = gtksignal_connect(Gtk2::Button->new(get_intf_status($interface)), clicked => sub { - system("/sbin/if" . (ethisup($interface) ? N("down") : N("up")) . " $interface"); + system("/sbin/if" . (ethisup($interface) ? "down" : "up") . " $interface"); $_[0]->set_label(get_intf_status($interface)); update(); }); @@ -944,7 +950,7 @@ Configure them first by clicking on 'Configure'"))); if ($net->{ifcfg}{$interface}{BOOTPROTO} ne "static") { delete @{$net->{ifcfg}{$interface}}{qw(IPADDR NETWORK NETMASK BROADCAST)}; } else { - if ($infos[1]->get_text ne "No ip") { + if ($infos[1]->get_text ne N("No IP")) { $net->{ifcfg}{$interface}{IPADDR} = $infos[1]->get_text; $net->{ifcfg}{$interface}{NETMASK} = $infos[3]->get_text; } @@ -966,7 +972,7 @@ Configure them first by clicking on 'Configure'"))); sub configure_net() { - my $dialog = ugtk2->new('drakconnect'); + my $dialog = ugtk2->new(N("Internet connection configuration")); my $exit_dialogsub = sub { Gtk2->main_quit }; if (!$net->{type}) { $in->ask_warn( @@ -978,7 +984,6 @@ Run the \"%s\" assistant from the Mandriva Linux Control Center", N("Set up a ne } unless ($::isEmbedded) { $dialog->{rwindow}->set_position('center'); - $dialog->{rwindow}->set_title(N("Internet connection configuration")); $dialog->{rwindow}->set_size_request(-1, -1); $dialog->{rwindow}->set_icon(gtkcreate_pixbuf("drakconnect")); } @@ -1007,7 +1012,7 @@ Run the \"%s\" assistant from the Mandriva Linux Control Center", N("Set up a ne } $infos[2*$i+1]->set_text(${$_->[1]}); $i++; - [ $_->[0], $c ]; + [ Gtk2::WrappedLabel->new($_->[0]), $c ]; } @conf_data ) ); @@ -1016,11 +1021,11 @@ Run the \"%s\" assistant from the Mandriva Linux Control Center", N("Set up a ne 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::Label->new(N("Connection type: ")), - Gtk2::Label->new(translate($net->{type})) ], + [ Gtk2::WrappedLabel->new(N("Connection type: ")), + Gtk2::WrappedLabel->new(translate($net->{type})) ], [ $int_label, $int_name ], - [ Gtk2::Label->new(N("Status:")), - $int_state = Gtk2::Label->new(N("Testing your connection...")) ] + [ Gtk2::WrappedLabel->new(N("Status:")), + $int_state = Gtk2::WrappedLabel->new(N("Testing your connection...")) ] ), 5), ), diff --git a/bin/drakfirewall b/bin/drakfirewall index 093543c..4588047 100755 --- a/bin/drakfirewall +++ b/bin/drakfirewall @@ -1,6 +1,6 @@ #!/usr/bin/perl -# Copyright (C) 1999-2005 Mandriva (pixel@mandrakesoft.com) +# Copyright (C) 1999-2006 Mandriva (pixel@mandrakesoft.com) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,6 +18,8 @@ use lib qw(/usr/lib/libDrakX); +# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX) +BEGIN { unshift @::textdomains, 'drakx-net' } use standalone; #- warning, standalone must be loaded very first, for 'explanations' use interactive; @@ -5,7 +5,7 @@ # modified by Florin Grad (florin@mandrakesoft.com) # wizardified by Olivier Blin (oblin@mandriva.com) # -# Copyright 2000-2005 Mandriva +# Copyright 2000-2006 Mandriva # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2, as @@ -24,13 +24,15 @@ use strict; use lib qw(/usr/lib/libDrakX); +# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX) +BEGIN { unshift @::textdomains, 'drakx-net' } use standalone; #- warning, standalone must be loaded very first, for 'explanations' use common; use detect_devices; use interactive; use network::network; -use network::ethernet; +use network::connection::ethernet; use run_program; use log; use c; @@ -45,21 +47,15 @@ my $cups_conf = "$::prefix/etc/cups/cupsd.conf"; my $in = 'interactive'->vnew('su'); -my ($kernel_version) = c::kernel_version() =~ /(...)/; -unless ($kernel_version >= 2.4) { - $in->ask_warn(N("Error"), N("Sorry, we support only 2.4 and above kernels.")); - $in->exit(-1); -} - my $net = {}; network::network::read_net_conf($net); my $modules_conf = modules::any_conf->read; -my %eth_intf = map { $_->[0] => join(': ', $_->[0], $_->[2]) } network::ethernet::get_eth_cards($modules_conf); +my %eth_intf = map { $_->[0] => join(': ', $_->[0], $_->[2]) } network::connection::ethernet::get_eth_cards($modules_conf); my $shorewall = network::shorewall::read(); my $choice; my $gw_enabled; -my ($net_interface_name, $lan_interface_name, $lan_intf, $internal_domain_name); +my ($lan_interface_name, $lan_intf, $internal_domain_name); my $use_dhcpd = 1; my $use_caching_dns = 1; my $use_caching_proxy = 1; @@ -121,17 +117,17 @@ What would you like to do?"); #- FIXME : not used for now choose_net_interface => { pre => sub { - $net_interface_name = $shorewall->{net_interface}; + $shorewall->{masq}{net_interface} = network::tools::get_default_gateway_interface($net); }, - name => translate($network::shorewall::ask_shorewall_interface_label), - data => network::shorewall::shorewall_interface_choices(\$net_interface_name), + name => N("Please select the network interface directly connected to the internet."), + data => [ { label => N("Net Device"), val => \$shorewall->{masq}{net_interface}, list => [ sort keys %{$net->{ifcfg}} ], format => sub { network::tools::get_interface_description($net, $_[0]) } } ], post => sub { - network::shorewall::set_net_interface($shorewall, $net_interface_name); - my $locals = @{$shorewall->{loc_interface}}; + network::shorewall::add_interface_to_net_zone($shorewall, $shorewall->{masq}{net_interface}); + my $locals = @{$shorewall->{loc_zone}}; if ($locals == 0) { return "end_no_lan_interface"; } elsif ($locals == 1) { - $lan_interface_name = $shorewall->{loc_interface}[0]; + $lan_interface_name = $shorewall->{loc_zone}[0]; return "one_lan_interface"; } else { return "choose_lan_interface"; @@ -155,7 +151,7 @@ I am about to setup your Local Area Network with that adapter.", format_interfac { name => N("Please choose what network adapter will be connected to your Local Area Network."), data => sub { - [ { type => "list", val => \$lan_interface_name, list => $shorewall->{loc_interface}, format => \&format_interfaces } ]; + [ { type => "list", val => \$lan_interface_name, list => $shorewall->{loc_zone}, format => \&format_interfaces } ]; }, post => sub { log::explanations("Choosing network device: $lan_interface_name"); @@ -212,10 +208,10 @@ I am about to setup your Local Area Network with that adapter.", format_interfac complete => sub { !$use_caching_dns || $::testing and return 0; #- install a caching name server if the specified DNS is the gateway - !$in->do_pkgs->ensure_is_installed('caching-nameserver', '/var/named/named.local'); + !$in->do_pkgs->ensure_is_installed('bind', '/usr/sbin/named'); }, post => sub { - services::set_status($_, $use_caching_dns) foreach qw(named caching-nameserver); + services::set_status($_, $use_caching_dns) foreach qw(named); return "dhcpd"; }, }, @@ -360,7 +356,7 @@ sub set_proxy_port { } sub gw_disable() { - my $_wait_disabl = $in->wait_message('', N("Disabling servers...")); + my $_wait_disabl = $in->wait_message(N("Please wait"), N("Disabling servers...")); return if $::testing; services::set_status($_, 0) foreach qw(dhcpd squid named); delete_proxy_ports(); @@ -384,7 +380,7 @@ sub gw_configure() { N("Configuring firewall...")); $shorewall->{disabled} = 0; - $shorewall->{masq_subnet} = "$lan_intf->{NETWORK}/$lan_intf->{NETMASK}"; + $shorewall->{masq}{subnet} = "$lan_intf->{NETWORK}/$lan_intf->{NETMASK}"; network::shorewall::write($shorewall); #- be sure that FORWARD_IPV4 is enabled in /etc/sysconfig/network diff --git a/bin/drakhosts b/bin/drakhosts index 32c6fd1..cdd5a22 100644 --- a/bin/drakhosts +++ b/bin/drakhosts @@ -1,6 +1,6 @@ #!/usr/bin/perl # -# Copyright (C) 2005 by Mandriva aginies _ateuh_ mandriva.com +# Copyright (C) 2005-2006 by Mandriva aginies _ateuh_ mandriva.com # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -28,6 +28,8 @@ use strict; use common; use network::network; +$ugtk2::wm_icon = 'IC-Dhost-48'; +use mygtk2 qw(gtknew); use ugtk2 qw(:ask :wrappers :create :dialogs); use constant FALSE => 0; @@ -47,7 +49,7 @@ my %size_groups = map { $_ => Gtk2::SizeGroup->new('horizontal') } qw(label widg my $label_and_widgets = sub { my ($label, $widget) = @_; gtkpack_(Gtk2::HBox->new(0,5), - 0, gtkadd_widget($size_groups{label}, $label), + 0, gtkadd_widget($size_groups{label}, gtknew('Label_Left', text => $label)), 1, gtkadd_widget($size_groups{widget}, $widget), ); }; @@ -74,7 +76,7 @@ sub write_conf_hosts() { } sub add_modify_entry { - my ($treeview, $wanted) = @_; + my ($treeview, $wanted, $title) = @_; my $model = $treeview->get_model; my $selection = $treeview->get_selection; my $iter; @@ -88,7 +90,7 @@ sub add_modify_entry { my $dialog = _create_dialog(); $dialog->set_transient_for($::main_window); - $dialog->set_title("Drakhosts $wanted entry"); + $dialog->set_title($title); $dialog->set_modal(1); $dialog->set_resizable(1); $dialog->set_size_request(300, -1); @@ -109,15 +111,12 @@ sub add_modify_entry { $text = N("Please delete information") if $wanted =~ /delete/; $text = N("Please add information") if $wanted =~ /add/; - gtkpack_($dialog->vbox, - 0, gtkadd(Gtk2::Frame->new($text), - gtkpack_(gtkset_border_width(Gtk2::VBox->new, 5), - 0, $label_and_widgets->(N("IP address:"), $ip), - 0, $label_and_widgets->(N("Host name:"), $hostname), - 0, $label_and_widgets->(N("Host Aliases:"), $alias), - ), - ), - 0, create_okcancel({ + gtkpack__($dialog->vbox, + gtknew('Title2', label => $text), + $label_and_widgets->(N("IP address:"), $ip), + $label_and_widgets->(N("Host name:"), $hostname), + $label_and_widgets->(N("Host Aliases:"), $alias), + create_okcancel({ cancel_clicked => sub { $dialog->destroy }, ok_clicked => sub { is_ip($ip->get_text) or err_dialog(N("Error!"), N("Please enter a valid IP address.")) and return; @@ -204,7 +203,7 @@ sub add_columns { # create model my $model = create_model(); -my $window = ugtk2->new("Drakhosts"); +my $window = ugtk2->new(N("Manage hosts definitions")); $::main_window = $window->{real_window}; $window->{rwindow}->set_size_request(500, 400) unless $::isEmbedded; my $W = $window->{window}; @@ -220,7 +219,7 @@ $treeview->signal_connect(button_press_event => sub { my $selection = $treeview->get_selection; my $iter = $selection->get_selected; if ($iter) { - add_modify_entry($treeview, "modify") if $event->type eq '2button-press'; + add_modify_entry($treeview, 'modify', N("Modify entry")) if $event->type eq '2button-press'; } }); @@ -234,20 +233,20 @@ my $okcancel = create_okcancel({ # main interface $W->add(gtkpack_(Gtk2::VBox->new(0,0), - if_(!$::isEmbedded, 0, Gtk2::Banner->new('IC-Dhost-48', N("DrakHOSTS manage hosts definitions"))), + if_(!$::isEmbedded, 0, Gtk2::Banner->new('IC-Dhost-48', N("Manage hosts definitions"))), #if_($::isEmbedded, 0, Gtk2::Label->new("Here you can add, remove and alter hosts definition.")), 1, gtkpack_(gtkset_border_width(Gtk2::HBox->new, 0), 1, create_scrolled_window($treeview), 0, gtkpack_(gtkset_border_width(create_vbox('start', 3)), 0, gtksignal_connect(Gtk2::Button->new(N("Add")), clicked => sub { - eval { add_modify_entry($treeview, "add") }; + eval { add_modify_entry($treeview, 'add', N("Add entry")) }; my $err = $@; if ($err) { err_dialog(N("Error"), N("Failed to add host.") . "\n\n" . $err); } }), 0, gtksignal_connect(Gtk2::Button->new(N("Modify")), clicked => sub { - eval { add_modify_entry($treeview, "modify") }; + eval { add_modify_entry($treeview, 'modify', N("Modify entry")) }; my $err = $@; if ($err) { err_dialog(N("Error"), N("Failed to Modify host.") . "\n\n" . $err); diff --git a/bin/drakids b/bin/drakids index d786cd2..77b4a82 100644 --- a/bin/drakids +++ b/bin/drakids @@ -2,6 +2,8 @@ use strict; use lib qw(/usr/lib/libDrakX); +# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX) +BEGIN { unshift @::textdomains, 'drakx-net' } use common; use standalone; @@ -30,10 +32,17 @@ $whitelist->set_headers_clickable(1); $whitelist->get_column(0)->signal_connect('clicked', \&sort_by_column, $whitelist->get_model); $whitelist->get_column(0)->set_sort_column_id(0); +my $i_m_ifw2 = member("--ifw2", @ARGV); +my $services_log = create_service_list('status'); +my $allowed_services = create_service_list(); +my $blocked_services = create_service_list(); + my $w = ugtk2->new(N("Interactive Firewall"), icon => "/usr/lib/libDrakX/icons/drakfirewall.png"); -my $ifw = network::ifw->new(dbus_object::system_bus(), sub { +my $ifw; +eval { + $ifw = network::ifw->new(dbus_object::system_bus(), sub { my ($_con, $msg) = @_; my $member = $msg->get_member; if ($member eq 'Attack') { @@ -49,11 +58,47 @@ my $ifw = network::ifw->new(dbus_object::system_bus(), sub { } elsif ($member eq 'ManageRequest') { $w->{window}->present; } -}); + }); +}; + +if ($@) { + err_dialog(N("Interactive Firewall"), N("Unable to contact daemon")); + ugtk2::exit; +} + init_lists(); gtkadd($w->{window}, gtknew('Notebook', children => [ + if_($i_m_ifw2, + gtknew('Label', text => N("Log")), + gtknew('VBox', spacing => 5, children => [ + 1, gtknew('ScrolledWindow', width => 600, height => 400, child => $services_log), + 0, gtknew('HButtonBox', layout => 'edge', children_loose => [ + gtknew('Button', text => N("Allow"), clicked => sub {}), + gtknew('Button', text => N("Block"), clicked => sub {}), + gtknew('Button', text => N("Close"), clicked => sub { Gtk2->main_quit }) + ]), + ]), + gtknew('Label', text => N("Allowed services")), + gtknew('VBox', spacing => 5, children => [ + 1, gtknew('ScrolledWindow', width => 600, height => 400, child => $allowed_services), + 0, gtknew('HButtonBox', layout => 'edge', children_loose => [ + gtknew('Button', text => N("Remove"), clicked => sub {}), + gtknew('Button', text => N("Block"), clicked => sub {}), + gtknew('Button', text => N("Close"), clicked => sub { Gtk2->main_quit }) + ]), + ]), + gtknew('Label', text => N("Blocked services")), + gtknew('VBox', spacing => 5, children => [ + 1, gtknew('ScrolledWindow', width => 600, height => 400, child => $blocked_services), + 0, gtknew('HButtonBox', layout => 'edge', children_loose => [ + gtknew('Button', text => N("Remove"), clicked => sub {}), + gtknew('Button', text => N("Allow"), clicked => sub {}), + gtknew('Button', text => N("Close"), clicked => sub { Gtk2->main_quit }) + ]), + ]), + ), gtknew('Label', text => N("Log")), gtknew('VBox', spacing => 5, children => [ 1, gtknew('ScrolledWindow', width => 600, height => 400, child => $loglist), @@ -231,6 +276,22 @@ sub attack_list_add { ]; } +sub create_service_list { + my ($o_status) = @_; + my $service_list = Gtk2::SimpleList->new( + N("Application") => 'text', + N("Service") => 'text', + if_($o_status, N("Status") => 'text'), + ); + N_("Allowed"); + N_("Blocked"); + $service_list->set_headers_clickable(1); + foreach (0, 1, if_($o_status, 2)) { + $service_list->get_column($_)->signal_connect('clicked', \&sort_by_column, $service_list->get_model); + } + $service_list; +} + #- may throw an exception sub init_loglist() { my @packets = $ifw->get_reports(1); @@ -254,7 +315,7 @@ sub get_selected_log() { uniq(map { $loglist->{data}[$_][0] } $loglist->get_selected_indices); } -sub clear_log { +sub clear_log() { eval { $ifw->clear_processed_reports; $ifw->send_alert_ack; diff --git a/bin/drakinvictus b/bin/drakinvictus new file mode 100755 index 0000000..ad6e142 --- /dev/null +++ b/bin/drakinvictus @@ -0,0 +1,151 @@ +#!/usr/bin/perl + +# Copyright (C) 2006 Mandriva +# Olivier Blin <blino@mandriva.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +use strict; + +use lib qw(/usr/lib/libDrakX); + +# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX) +BEGIN { unshift @::textdomains, 'drakx-net' } +use standalone; + +use common; +use network::invictus; +use network::network; +use detect_devices; +use mygtk2 qw(gtknew); +use ugtk2 qw(:create :helpers :wrappers :dialogs); + +$ugtk2::wm_icon = 'invictus-16'; +my $title = N("Invictus Firewall"); +my $w = ugtk2->new($title); +$::main_window = $w->{real_window}; #- so that transient_for is defined for wait messages and dialogs + +my $net = {}; +network::network::read_net_conf($net); +my @interfaces = detect_devices::get_lan_interfaces; + +my $invictus = {}; +network::invictus::read_config($invictus); + +my %interface_addresses = map { $_ => { + real_address => gtknew('Entry', text => $invictus->{ucarp}{$_}{SRCIP}), + virtual_address => gtknew('Entry', text => $invictus->{ucarp}{$_}{VIRTIP}), + vid => do { my $w = gtknew('Entry', text => $invictus->{ucarp}{$_}{VHID}); $w->set_width_chars(5); $w }, +} } @interfaces; + +my $master_checkbutton = gtknew('CheckButton', text => N("Start as master"), active => do { + my $m = find { $_->{TAKEOVER} } values %{$invictus->{ucarp}}; + $m && text2bool($m->{TAKEOVER}); +}); +my $password_entry = gtknew('Entry', text => do { + my $p = find { $_->{PASSWORD} } values %{$invictus->{ucarp}}; + $p && $p->{PASSWORD}; +}); +$password_entry->set_visibility(0); +my $ct_sync_interface_list; +my $cmarkbit_entry; + +sub apply_invictus_firewall() { + require interactive; + my $in = 'interactive'->vnew; + $in->do_pkgs->ensure_is_installed('invictus-firewall', '/etc/rc.d/init.d/ct_sync') or return; + $in->do_pkgs->ensure_is_installed('ucarp', '/etc/rc.d/init.d/ucarp') or return; + + my $password = $password_entry->get_text; + $password or err_dialog(N("Error"), N("A password is required.")), return; + foreach (@interfaces) { + @{$invictus->{ucarp}{$_}}{qw(INTERFACE SRCIP VIRTIP VHID PASSWORD TAKEOVER)} = ( + $_, + (map { $_->get_text } @{$interface_addresses{$_}}{qw(real_address virtual_address vid)}), + $password, + bool2yesno($master_checkbutton->get_active), + ); + } + network::invictus::write_config($invictus); + + require services; + services::enable('ct_sync'); + services::enable('ucarp'); +} + +sub update_ct_sync_state() { + my $enable_ct_sync = text2bool($invictus->{ct_sync}{ENABLE}); + $_->set_sensitive($enable_ct_sync) foreach $ct_sync_interface_list, $cmarkbit_entry; + foreach my $interface (@interfaces) { + my $enable = !$enable_ct_sync || $interface ne $invictus->{ct_sync}{INTERFACE}; + $_->set_sensitive($enable) foreach values %{$interface_addresses{$interface}}; + } +} + +gtkadd($w->{window}, + gtknew('VBox', spacing => 5, children_tight => [ + $::isEmbedded ? () : Gtk2::Banner->new('invictus-52', $title), + gtknew('WrappedLabel', text => N("This tool allows to set up network interfaces failover and firewall replication.")), + gtknew('Frame', border_width => 5, + text => N("Network redundancy (leave empty if interface is not used)"), + child => gtknew('VBox', border_width => 10, children_tight => [ + gtknew('Table', children => [ + [ N("Interface"), N("Real address"), N("Virtual shared address"), N("Virtual ID") ], + (map { + [ $_, @{$interface_addresses{$_}}{qw(real_address virtual_address vid)} ]; + } @interfaces), + ]), + gtknew('HBox', spacing => 5, children_tight => [ N("Password"), $password_entry ]), + $master_checkbutton, + ])), + gtknew('Frame', border_width => 5, + text => N("Firewall replication"), + child => gtknew('VBox', border_width => 10, children_tight => [ + gtknew('CheckButton', text => N("Synchronize firewall conntrack tables"), + active => text2bool($invictus->{ct_sync}{ENABLE}), + toggled => sub { + $invictus->{ct_sync}{ENABLE} = bool2yesno($_[0]->get_active); + update_ct_sync_state(); + }), + gtknew('HBox', spacing => 5, children => [ + 0, N("Synchronization network interface"), + 1, $ct_sync_interface_list = + gtknew('ComboBox', list => \@interfaces, text => $invictus->{ct_sync}{INTERFACE}, + changed => sub { + $invictus->{ct_sync}{INTERFACE} = $_[0]->get_active_text; + update_ct_sync_state(); + }), + ]), + gtknew('HBox', spacing => 5, children_tight => [ + N("Connection mark bit"), + $cmarkbit_entry = + gtknew('ComboBox', list => [ 0 .. 31 ], text => $invictus->{ct_sync}{CMARKBIT}, changed => sub { + $invictus->{ct_sync}{CMARKBIT} = $_[0]->get_active_text; + }), + ]), + ])), + gtknew('HButtonBox', layout => 'edge', children_tight => [ + gtknew('Button', text => N("Apply"), clicked => \&apply_invictus_firewall), + gtknew('Button', text => N("Quit"), clicked => sub { $w->exit }), + ]), + ]), + ); + + + + +update_ct_sync_state(); + +$w->main; diff --git a/bin/draknetcenter b/bin/draknetcenter new file mode 100755 index 0000000..280be2d --- /dev/null +++ b/bin/draknetcenter @@ -0,0 +1,132 @@ +#!/usr/bin/perl +# Olivier Blin, 2007 <oblin@mandriva.com> +# Licensed under the GPL + + +use strict; +use lib qw(lib /usr/lib/libDrakX); + +# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX) +BEGIN { unshift @::textdomains, 'drakx-net' } + +use standalone; +use common; +use run_program; +use detect_devices; +use interactive; +use mygtk2; +use ugtk2 qw(:create :helpers :wrappers); +use Gtk2::SimpleList; +use network::monitor; +use network::signal_strength; +use network::network; +use network::tools; +use network::connection; +use network::connection::wireless; +use network::connection::cellular_card; + +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 = map { $_->get_connections(automatic_only => 1) } network::connection::get_types; +@connections = reverse(uniq_ { $_->{device} } reverse(@connections)); + +sub build_networks_list { + my ($connection) = @_; + + #- from drakroam + my %pixbufs = + ( + state => { map { $_ => gtkcreate_pixbuf($_) } qw(connected disconnected refresh) }, + link_level => { map { + $_ => gtkcreate_pixbuf('wifi-' . sprintf('%03d', $_) . '.png')->scale_simple(24, 24, 'hyper'); + } qw(20 40 60 80 100) }, + encryption => { map { + $_ => gtkcreate_pixbuf("encryption-$_-24.png"); + } qw(open weak strong) }, + ); + + #- from drakroam + my $networks_list = Gtk2::SimpleList->new( + "AP" => "hidden", + '' => "pixbuf", + '' => "pixbuf", + N("Signal strength") => "pixbuf", + N("SSID") => "text", + ); + $networks_list->get_selection->set_mode('single'); + $networks_list->set_headers_visible(0); + + my $net = {}; + network::network::read_net_conf($net); + + #- from drakroam::update_networks() + $connection->{networks} = $connection->get_networks; + $connection->{network} ||= find { $connection->{networks}{$_}{current} } keys %{$connection->{networks}}; + my $routes = network::tools::get_routes(); + my $interface = $connection->get_interface; + my $connected = exists $routes->{$interface}{network}; + + + $_->{configured} = $connection->network_is_configured($_) foreach values %{$connection->{networks}}; + my @networks = sort { + $b->{configured} <=> $a->{configured} || $b->{signal_strength} <=> $a->{signal_strength} || $a->{name} cmp $b->{name}; + } values %{$connection->{networks}}; + my @valuable_networks = splice @networks, 0, 3; + foreach (@valuable_networks) { + my $ap = $_->{ap}; + push @{$networks_list->{data}}, [ + $ap || $_->{name}, + $_->{current} ? $connected ? $pixbufs{state}{connected} : $pixbufs{state}{refresh} : undef, + $pixbufs{encryption}{$_->{flags} =~ /WPA/i ? 'strong' : $_->{flags} =~ /WEP/i ? 'weak' : 'open'}, + network::signal_strength::get_strength_icon($_), + !$_->{essid} && exists $net->{wireless}{$ap} && $net->{wireless}{$ap}{WIRELESS_ESSID} || $_->{name}, + ]; + } + + $networks_list; +} + +sub gtkset_image { + my ($w, $file, $o_size) = @_; + my $image = $o_size + ? Gtk2::Image->new_from_pixbuf(gtkcreate_pixbuf($file)->scale_simple($o_size, $o_size, 'hyper')) + : gtknew('Image', file => $file); + $w->set_image($image); + $w; +} + +gtkadd($w->{window}, + gtknew('VBox', spacing => 5, children => [ + $::isEmbedded ? () : (0, Gtk2::Banner->new($icon, $title)), + 1, gtknew('ScrolledWindow', width => 500, height => 300, child => gtknew('VBox', spacing => 5, children_tight => [ + map { + gtknew('VBox', children_tight => [ + gtknew('HBox', children_tight => [ + gtknew('Image', file => $_->get_type_icon), + $_->get_description, + ]), + gtknew('HBox', children => [ + 0, gtknew('Label', padding => [ 20, 0 ]), + 0, gtknew('VBox', children_tight => [ + gtknew('HBox', children_tight => [ + gtkset_image(gtknew('Button'), 'connected'), + gtkset_image(gtknew('Button'), 'monitor-24'), + gtkset_image(gtknew('Button'), 'configure-24'), + ($_->can('get_networks') ? (0, gtkset_image(gtknew('Button'), 'refresh')) : ()), + ]), + ]), + ($_->can('get_networks') && !$_->network_scan_is_slow ? (1, build_networks_list($_)) : ()), + ]), + ]); + } @connections, + ])), + ]), + ); + +$w->main; diff --git a/bin/draknetprofile b/bin/draknetprofile new file mode 100755 index 0000000..49ca287 --- /dev/null +++ b/bin/draknetprofile @@ -0,0 +1,153 @@ +#!/usr/bin/perl + +# Copyright (C) 2006 Mandriva +# Olivier Blin <blino@mandriva.com> +# Thierry Vignaud <tvignaud@mandriva.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +use strict; + +use lib qw(/usr/lib/libDrakX); + +# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX) +BEGIN { unshift @::textdomains, 'drakx-net' } +use standalone; + +use common; +use network::network; +use mygtk2; +use Gtk2::SimpleList; +use ugtk2 qw(:create :helpers :wrappers :dialogs); + +$ugtk2::wm_icon = 'draknetprofile-16'; +my $title = N("Network profiles"); +my $w = ugtk2->new($title); +$::main_window = $w->{real_window}; #- so that transient_for is defined for wait messages and dialogs + +my $net = {}; +my @profiles; +my $default_profile = "default"; +my %buttons; + +package Gtk2::CellRendererRadio; + +sub new { + my $renderer = Gtk2::CellRendererToggle->new; + $renderer->set_radio(1); + $renderer->set_property('mode', 'inert'); + $renderer; +} + +1; + +package main; + +Gtk2::SimpleList->add_column_type( + 'radio', + type => 'Glib::Boolean', + renderer => 'Gtk2::CellRendererRadio', + attr => 'active', +); + +my $profiles_list = Gtk2::SimpleList->new( + "" => 'radio', + N("Profile") => 'text', +); +$profiles_list->get_selection->signal_connect('changed' => sub { + my ($index) = $profiles_list->get_selected_indices; + $_->set_sensitive(defined $index) foreach values %buttons; + }); + +sub get_selected_profile() { + my ($index) = $profiles_list->get_selected_indices; + defined $index && $profiles_list->{data}[$index][1]; +} + +sub update_profiles() { + my $previous_profile = get_selected_profile(); + network::network::netprofile_read($net); + @profiles = network::network::netprofile_list(); + @{$profiles_list->{data}} = map { [ $_ eq $net->{PROFILE}, $_ ] } @profiles; + my $index = eval { find_index { $_ eq $previous_profile } @profiles }; + $profiles_list->select($index) if defined $index; +} + +sub set_selected_profile() { + my $profile = get_selected_profile(); + gtkset_mousecursor_wait($w->{window}->window); + gtkflush(); + network::network::netprofile_set($net, $profile); + gtkset_mousecursor_normal($w->{window}->window); + update_profiles(); +} + +sub clone_profile() { + my $source_profile = get_selected_profile(); + my $dialog = _create_dialog(N("New profile...")); + my $entry_dialog = Gtk2::Entry->new; + gtkpack($dialog->vbox, + Gtk2::WrappedLabel->new(N("Name of the profile to create (the new profile is created as a copy of the current one):")), + $entry_dialog, + ); + gtkpack($dialog->action_area, + gtksignal_connect(Gtk2::Button->new(N("Cancel")), + clicked => sub { $dialog->destroy }), + gtksignal_connect(my $bok = Gtk2::Button->new(N("Ok")), clicked => sub { + my $dest_profile = $entry_dialog->get_text; + # netprofile does not like spaces in profile names... + $dest_profile =~ s/ /_/g; + if (member($dest_profile, @profiles)) { + err_dialog(N("Error"), N("The \"%s\" profile already exists!", $dest_profile), { transient => $dialog }); + return 1; + } + $dialog->destroy; + network::network::netprofile_clone($source_profile, $dest_profile); + update_profiles(); + }), + ); + $bok->can_default(1); + $bok->grab_default; + $dialog->show_all; +} + +sub delete_selected_profile() { + my $profile = get_selected_profile(); + if ($profile eq $default_profile) { + warn_dialog(N("Warning"), N("You can not delete the default profile")); + } elsif ($profile eq $net->{PROFILE}) { + warn_dialog(N("Warning"), N("You can not delete the current profile")); + } else { + network::network::netprofile_delete($profile); + update_profiles(); + } +} + +gtkadd($w->{window}, + gtknew('VBox', spacing => 5, children => [ + $::isEmbedded ? () : (0, Gtk2::Banner->new('draknetprofile', $title)), + 0, gtknew('WrappedLabel', text => N("This tool allows to activate an existing network profile, and to manage (clone, delete) profiles.") . "\n\n" . N("To modify a profile, you have to activate it first.")), + 1, gtknew('ScrolledWindow', width => 300, height => 150, child => $profiles_list), + 0, gtknew('HButtonBox', children_loose => [ + $buttons{activate} = gtknew('Button', text => N("Activate"), clicked => \&set_selected_profile), + $buttons{clone} = gtknew('Button', text => N("Clone"), clicked => \&clone_profile), + $buttons{delete} = gtknew('Button', text => N("Delete"), clicked => \&delete_selected_profile), + gtknew('Button', text => N("Quit"), clicked => sub { Gtk2->main_quit }), + ]), + ]), + ); + +update_profiles(); +$w->main; diff --git a/bin/draknfs b/bin/draknfs index f1bd916..a81d62d 100644 --- a/bin/draknfs +++ b/bin/draknfs @@ -1,6 +1,6 @@ #!/usr/bin/perl # -# Copyright (C) 2005 by Mandriva aginies _ateuh_ mandriva.com +# Copyright (C) 2005-2006 by Mandriva aginies _ateuh_ mandriva.com # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -17,18 +17,18 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. -my $version = "0.3"; - use strict; use lib qw(/usr/lib/libDrakX); use standalone; use common; use network::network; use interactive; +$ugtk2::wm_icon = 'IC-NFS-48'; +use mygtk2 qw(gtknew gtkset); use ugtk2 qw(:ask :wrappers :create :dialogs); my $in = 'interactive'->vnew('su'); -$in->do_pkgs->ensure_is_installed('nfs-utils', '/usr/sbin/rpc.nfsd') or return; +$in->do_pkgs->ensure_is_installed('nfs-utils', '/sbin/rpc.statd') or return; use constant COLUMN_DIR => 0; use constant COLUMN_ACCESS => 1; @@ -55,13 +55,14 @@ my @yesno = qw(yes no); sub get_items() { my @items = ( - [ "/_File", undef, undef, undef, '<Branch>', ], - [ "/_File/_Write conf", undef, \&write_conf, 1, '<StockItem>', 'gtk-execute' ], - [ "/_File/_Exit", undef, \&quit_all, 1, '<StockItem>', 'gtk-quit' ], + [ N("/_File"), undef, undef, undef, '<Branch>', ], + [ N("/_File") . N("/_Write conf"), undef, \&write_conf, 1, '<Item>', ], + [ N("/_File") . N("/_Quit"), N("<control>Q"), \&quit_all, 1, '<Item>', ], + - [ "/_NFS Server", undef, undef, undef, '<Branch>', ], - [ "/_NFS Server/_Restart", undef, \&restart_dialog, 1, '<StockItem>', 'gtk-execute' ], - [ "/_NFS Server/R_eload", undef, \&reload_dialog, 1, '<StockItem>', 'gtk-refresh' ], + [ N("/_NFS Server"), undef, undef, undef, '<Branch>', ], + [ N("/_NFS Server") . N("/_Restart"), undef, \&restart_dialog, 1, '<Item>', ], + [ N("/_NFS Server") . N("/R_eload"), undef, \&reload_dialog, 1, '<Item>', ], ); return @items; } @@ -81,18 +82,18 @@ sub reload_dialog() { sub wait_action { my ($cmd) = @_; my $w = $in->wait_message(N("NFS server"), N("Restarting/Reloading NFS server...")); - run_program::get_stdout($cmd) !~ /unknown|error/ or err_dialog(N("Error!"), N("Error Restarting/Reloading NFS server")) and return; + run_program::get_stdout($cmd) !~ /unknown|error/ or err_dialog(N("Error"), N("Error Restarting/Reloading NFS server")) and return; undef $w; } my %size_groups = map { $_ => Gtk2::SizeGroup->new('horizontal') } qw(label widget button); my $label_and_widgets = sub { my ($label, $widget, $button) = @_; - gtkpack_(Gtk2::HBox->new(0,0), - 0, gtkadd_widget($size_groups{label}, $label), + gtknew('HBox', children => [ + 0, gtkadd_widget($size_groups{label}, gtknew('Label_Left', text => $label)), 0, gtkadd_widget($size_groups{widget}, $widget), 0, gtkadd_widget($size_groups{button}, $button), - ); + ]); }; my $fdwidget = sub { @@ -102,7 +103,7 @@ my $fdwidget = sub { $fd->signal_connect("destroy", sub { $fd->hide }); $fd->ok_button->signal_connect(clicked => sub { my $file = $fd->get_filename; - -d $file or err_dialog(N("Error!"), N("Should be a directory.")) and return; + -d $file or err_dialog(N("Error"), N("Should be a directory.")) and return; $data->set_text($file); $fd->hide; }, $fd); @@ -168,46 +169,21 @@ my %adv_options = ( secured => N("Secured Connection:"), ro => N("Read-Only share:"), ); -my $help_global = join("\n\n\n", N("<span weight=\"bold\">Advanced Options</span>"), -N("<span foreground=\"royalblue3\">%s:</span> this option requires that requests originate on an internet port less than IPPORT_RESERVED (1024). This option is on by default.", $adv_options{secured}), -N("<span foreground=\"royalblue3\">%s:</span> allow either only read or both read and write requests on this NFS volume. The default is to disallow any request which changes the filesystem. This can also be made explicit by using this option.", $adv_options{ro}), -N("<span foreground=\"royalblue3\">%s:</span> disallows the NFS server to violate the NFS protocol and to reply to requests before any changes made by these requests have been committed to stable storage (e.g. disc drive).", $adv_options{sync}), +my $help_global = join("\n\n\n", '<b><big>' . N("Advanced Options") . '</big></b>', +N("<span foreground=\"royalblue3\">%s</span> this option requires that requests originate on an internet port less than IPPORT_RESERVED (1024). This option is on by default.", $adv_options{secured}), +N("<span foreground=\"royalblue3\">%s</span> allow either only read or both read and write requests on this NFS volume. The default is to disallow any request which changes the filesystem. This can also be made explicit by using this option.", $adv_options{ro}), +N("<span foreground=\"royalblue3\">%s</span> disallows the NFS server to violate the NFS protocol and to reply to requests before any changes made by these requests have been committed to stable storage (e.g. disc drive).", $adv_options{sync}), ); -sub create_pango_help_box { - # perl code from draksec - my ($help) = @_; - my $text = Gtk2::TextView->new; - use Gtk2::Pango; - my %common_opts = ('left-margin' => '10', 'right-margin' => '10'); - gtktext_insert($text, [ map { - if (s!^/span>!!) { - [ $_, \%common_opts ]; - } elsif (s!span !!) { - my %tags = %common_opts; - while (s!(\w+?)="(\w+?)"!!) { - $tags{weight} ||= Gtk2::Pango->PANGO_WEIGHT_BOLD if $1 eq 'foreground'; - $tags{$1} = $2 eq "bold" ? Gtk2::Pango->PANGO_WEIGHT_BOLD : $2; - } - s/^>//; - [ $_, \%tags ]; - } else { - [ $_, \%common_opts ]; - } - } split("<", formatAlaTeX($help)) ]); - gtkset_size_request(create_scrolled_window($text), 350, 300); -} - sub help_b { - my ($tittle, $help_data) = @_; - gtksignal_connect(new Gtk2::Button->new(N("Information")), clicked => sub { - my $dialog = _create_dialog(); - $dialog->set_transient_for($::main_window); - $dialog->set_title(N("Help")); - $dialog->set_modal(1); + my ($help_data) = @_; + gtksignal_connect(gtknew('Button', text => N("Information")), clicked => sub { + my $dialog = _create_dialog(N("Help"), { transient_for => $::main_window, modal => 1 }); gtkpack_($dialog->vbox, - 1, create_pango_help_box($help_data), - 0, gtksignal_connect(Gtk2::Button->new(N("Close")), clicked => sub { + 1, gtknew('ScrolledWindow', width => 350, height => 300, + child => gtknew('TextView', text => ugtk2::markup_to_TextView_format(formatAlaTeX($help_data))) + ), + 0, gtknew('Button', text => N("Close"), clicked => sub { $dialog->destroy; } ), @@ -220,7 +196,7 @@ sub help_b { sub get_access_list() { my $net = {}; network::network::read_net_conf($net); - my $interface ||= $net->{net_interface}; + my $interface = $net->{net_interface}; my $ip_address = network::tools::get_interface_ip_address($net, $interface); my $domain = chomp_(`dnsdomainname`); my @o = split(/\./, $ip_address); @@ -250,12 +226,8 @@ sub get_data_from_id { sub get_user_or_group { my ($what) = @_; my $conf = "/etc/" . $what; - my @data; local $_; - foreach (cat_($conf)) { - push @data, "$1 [$2]" if m/^([^#:]+):[^:]+:([^:]+):/ and $2 > 499; - } - push @data, " "; - return sort(@data); + my @data = map { if_(m/^([^#:]+):[^:]+:([^:]+):/ && $2 > 499, "$1 [$2]") } cat_($conf); + return sort(@data, " "); } @@ -268,11 +240,11 @@ sub add_modify_entry { my ($lr, $luserid, $lsecure, $lsync, $lr_data, $lsync_data, $lsecure_data); undef $i; undef $iter; - $_ = Gtk2::Entry->new foreach $dir, $options; + $_ = gtknew('Entry') foreach $dir, $options; $_ = Gtk2::OptionMenu->new foreach $lr, $luserid, $lsecure, $lsync; $access = Gtk2::Combo->new; -# $access = Gtk2::ComboBox->new_text; +# $access = gtknew('ComboBox'); my @access_list = get_access_list(); # foreach (@access_list) { # $_ and $access->append_text($_); @@ -285,20 +257,15 @@ sub add_modify_entry { $lsecure->set_popdown_strings(@yesno); my $file_dialog = $fdwidget->($dir); - my $button = Gtk2::Button->new(N("Directory")); + my $button = gtknew('Button', text => N("Directory")); $button->signal_connect(clicked => sub { $file_dialog->show }); # test if modify or add a nfs share - my $dialog = _create_dialog(); - $dialog->set_transient_for($::main_window); + my $dialog = _create_dialog(N("Draknfs entry"), { transient_for => $::main_window, modal => 1 }); local $::main_window = $dialog; - $dialog->set_title("Draknfs entry"); - $dialog->set_position('center'); - $dialog->set_modal(1); - $dialog->set_resizable(1); - my $anonuid = Gtk2::ComboBox->new_with_strings([ get_user_or_group('passwd') ]); - my $anongid = Gtk2::ComboBox->new_with_strings([ get_user_or_group('group') ]); + my $anonuid = gtknew('ComboBox', list => [ get_user_or_group('passwd') ]); + my $anongid = gtknew('ComboBox', list => [ get_user_or_group('group') ]); $_->set_wrap_width(3) foreach $anonuid, $anongid; if ($wanted =~ /modify/) { @@ -374,41 +341,29 @@ sub add_modify_entry { } my $expender = Gtk2::Expander->new('Advanced options'); - $expender->add(gtkpack_(Gtk2::VBox->new, - 0, $label_and_widgets->($adv_options{sync}, $lsync, help_b(N_("Advanced Options Help"), $help_global)), - 0, $label_and_widgets->($adv_options{secured}, $lsecure, ""), - 0, $label_and_widgets->($adv_options{ro}, $lr, ""), - ), + $expender->add(gtknew('VBox', spacing => 5, children_tight => [ + $label_and_widgets->($adv_options{sync}, $lsync, help_b($help_global)), + $label_and_widgets->($adv_options{secured}, $lsecure, ""), + $label_and_widgets->($adv_options{ro}, $lr, ""), + ]), ); $expender->signal_connect(activate => sub { - gtkset_size_request($dialog, -1, -1); + gtkset($dialog); gtkflush(); }); - gtkpack_($dialog->vbox, - 0, gtkadd(Gtk2::Frame->new(N("NFS directory")), - gtkpack_(gtkset_border_width(Gtk2::VBox->new, 5), - 0, $label_and_widgets->(N("Directory:"), $dir, $button), - ), - ), - 0, gtkadd(Gtk2::Frame->new(N("Host access")), - gtkpack_(gtkset_border_width(Gtk2::VBox->new, 5), - 0, $label_and_widgets->(N("Access:"), $access, help_b(N_("Hosts Access"), $help_access)), - ), - ), - 0, gtkadd(Gtk2::Frame->new(N("User ID Mapping")), - gtkpack_(gtkset_border_width(Gtk2::VBox->new, 5), - 0, $label_and_widgets->(N("User ID:"), $luserid, help_b(N_("Help User ID"), $help_userid)), - 0, $label_and_widgets->(N("Anonymous user ID:"), $anonuid, ""), - 0, $label_and_widgets->(N("Anonymous Group ID:"), $anongid, ""), - ), - ), - 0, gtkadd(Gtk2::Frame->new(""), - gtkpack_(gtkset_border_width(Gtk2::VBox->new, 5), - 0, $expender, - ), - ), - 0, create_okcancel({ + $dialog->vbox->set_spacing(5); + gtkpack__($dialog->vbox, + gtknew('Title2', label => N("NFS directory")), + $label_and_widgets->(N("Directory:"), $dir, $button), + gtknew('Title2', label => N("Host access")), + $label_and_widgets->(N("Access:"), $access, help_b($help_access)), + gtknew('Title2', label => N("User ID Mapping")), + $label_and_widgets->(N("User ID:"), $luserid, help_b($help_userid)), + $label_and_widgets->(N("Anonymous user ID:"), $anonuid, ""), + $label_and_widgets->(N("Anonymous Group ID:"), $anongid, ""), + $expender, + create_okcancel({ cancel_clicked => sub { $dialog->destroy }, ok_clicked => sub { my ($anonu, $anong); @@ -441,10 +396,13 @@ sub add_modify_entry { my $all_right = join(",", grep { defined $_ } $luserid_toput, $anonu, $anong, $lsync_data, $lsecure_data, $lr_data); my $test_dir = $dir->get_text; - mkdir_p($test_dir) or err_dialog(N("Error!"), N("Can't create this directory.")) and return; + if (! $test_dir) { + err_dialog(N("Error"), N("Please specify a directory to share.")) and return; + } + mkdir_p($test_dir) or err_dialog(N("Error"), N("Can't create this directory.")) and return; #my $test_access = $access->child->get_text; my $test_access = $access->entry->get_text; - $test_access or err_dialog(N("Error!"), N("You must specify hosts access.")) and return; + $test_access or err_dialog(N("Error"), N("You must specify hosts access.")) and return; if ($wanted =~ /add/) { $iter = $model->append; $i = "-1"; @@ -477,7 +435,7 @@ sub add_modify_entry { } sub remove_entry { - my ($widget, $treeview) = @_; + my ($treeview) = @_; my $model = $treeview->get_model; my $selection = $treeview->get_selection; my $iter = $selection->get_selected; @@ -536,14 +494,14 @@ sub cell_edited { if ($column == COLUMN_DIR) { my $i = ($path->get_indices)[0]; $listshare[$i]{dir} = $new_text; - -d $new_text or err_dialog(N("Error!"), N("Please enter a directory to share.")) and return; + -d $new_text or err_dialog(N("Error"), N("Please enter a directory to share.")) and return; $model->set($iter, $column, $listshare[$i]{dir}); } elsif ($column == COLUMN_ACCESS) { my $i = ($path->get_indices)[0]; $listshare[$i]{access} = $new_text; $model->set($iter, $column, $listshare[$i]{access}); } elsif ($column == COLUMN_RIGHT) { - err_dialog(N("Error!"), N("Please use the modify button to set right access.")) and return; + err_dialog(N("Error"), N("Please use the modify button to set right access.")) and return; } elsif ($column == COLUMN_OPTIONS) { my $i = ($path->get_indices)[0]; $listshare[$i]{options} = $new_text; @@ -558,7 +516,7 @@ sub cell_edited { # create model my $model = create_model(); -my $window = ugtk2->new("DrakNFS"); +my $window = ugtk2->new(N("Manage NFS shares")); $::main_window = $window->{real_window}; $window->{rwindow}->set_size_request(550, 400) unless $::isEmbedded; $window->{rwindow}->set_position('center') if !$::isEmbedded; @@ -595,38 +553,38 @@ my $okcancel = create_okcancel({ ); # main interface -$W->add(gtkpack_(Gtk2::VBox->new(0,0), +$W->add(gtknew('VBox', children => [ 0, $menu, - if_(!$::isEmbedded, 0, Gtk2::Banner->new('IC-NFS-48', N("DrakNFS manage NFS shares"))), - #if_($::isEmbedded, 0, Gtk2::Label->new("Here you can add, remove and alter NFS shares.")), - 1, gtkpack_(gtkset_border_width(Gtk2::HBox->new, 0), - 1, create_scrolled_window($treeview), + 0, Gtk2::Banner->new('IC-NFS-48', N("DrakNFS manage NFS shares")), + #if_($::isEmbedded, 0, gtknew('Label', text => "Here you can add, remove and alter NFS shares.")), + 1, gtknew('HBox', border_width => 0, children => [ + 1, gtknew('ScrolledWindow', child => $treeview), 0, gtkpack_(create_vbox('start'), - 0, gtksignal_connect(Gtk2::Button->new(N("Add")), clicked => sub { + 0, gtknew('Button', text => N("Add"), clicked => sub { eval { add_modify_entry($treeview, "add") }; my $err = $@; if ($err) { err_dialog(N("Error"), N("Failed to add NFS share.") . "\n\n" . $err); } }), - 0, gtksignal_connect(Gtk2::Button->new(N("Modify")), clicked => sub { + 0, gtknew('Button', text => N("Modify"), clicked => sub { eval { add_modify_entry($treeview, "modify") }; my $err = $@; if ($err) { err_dialog(N("Error"), N("Failed to Modify NFS share.") . "\n\n" . $err); } }), - 0, gtksignal_connect(Gtk2::Button->new(N("Remove")), clicked => sub { - eval { remove_entry($model, $treeview) }; + 0, gtknew('Button', text => N("Remove"), clicked => sub { + eval { remove_entry($treeview) }; my $err = $@; if ($err) { err_dialog(N("Error"), N("Failed to remove an NFS share.") . "\n\n" . $err); } }), ), - ), + ]), 0, $okcancel, - ), + ]), ); $W->show_all; diff --git a/bin/drakproxy b/bin/drakproxy index 9ef2f28..0752f7b 100755 --- a/bin/drakproxy +++ b/bin/drakproxy @@ -2,7 +2,7 @@ # DrakProxy -# Copyright (C) 1999-2005 Mandriva (damien@mandrakesoft.com) +# Copyright (C) 1999-2006 Mandriva (damien@mandrakesoft.com) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -20,6 +20,8 @@ use lib qw(/usr/lib/libDrakX); +# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX) +BEGIN { unshift @::textdomains, 'drakx-net' } use standalone; #- warning, standalone must be loaded very first, for 'explanations' use interactive; use network::network; @@ -29,6 +31,11 @@ use common; $ugtk2::wm_icon = "/usr/share/mcc/themes/default/drakproxy-mdk.png"; my $u = { getVarsFromSh('/etc/profile.d/proxy.sh') }; my $in = 'interactive'->vnew('su'); -network::network::miscellaneous_choose($in, $u); -network::network::proxy_configure($u); +if (network::network::miscellaneous_choose($in, $u)) { + network::network::proxy_configure($u); + if ($in->ask_okcancel(N("Warning"), N("You need to log out and back in again for changes to take effect"), 1)) { + my $wm = any::running_window_manager(); + $wm and any::ask_window_manager_to_logout($wm); + } +} $in->exit(0); diff --git a/bin/drakroam b/bin/drakroam index 5511e76..a642aec 100755 --- a/bin/drakroam +++ b/bin/drakroam @@ -2,12 +2,14 @@ # drakroam: wireless network roaming GUI # Austin Acton, 2004 <austin@mandriva.org> -# Olivier Blin, 2005 <oblin@mandriva.com> +# Olivier Blin, 2005-2006 <oblin@mandriva.com> # Licensed under the GPL use strict; use lib qw(/usr/lib/libDrakX); +# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX) +BEGIN { unshift @::textdomains, 'drakx-net' } use standalone; use common; use run_program; @@ -16,33 +18,104 @@ use interactive; use mygtk2; use ugtk2 qw(:create :helpers :wrappers); use Gtk2::SimpleList; -use network::ethernet; use network::monitor; +use network::signal_strength; use network::network; use network::tools; -use network::wireless; - +use network::connection; +use network::connection::wireless; +use network::connection::cellular_card; +use modules; + +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 $in = 'interactive'->vnew('su'); -my $arg_ap; -/^--ap=(.*)/ and $arg_ap = $1 foreach @ARGV; +my %args = map { if_(/^--(\w+)=(.*)$/ && member($1, qw(ap interface)), $1 => $2) } @ARGV; + +my @connection_types = qw(network::connection::wireless network::connection::cellular_card); +my @connections; +my $connection; + +my %buttons; + +my $model = Gtk2::ListStore->new('Gtk2::Gdk::Pixbuf', 'Glib::String'); +my $connections_combo = Gtk2::ComboBox->new($model); +$connections_combo = Gtk2::ComboBox->new($model); +my $pix_r = Gtk2::CellRendererPixbuf->new; +$connections_combo->pack_start($pix_r, 0,); +$connections_combo->add_attribute($pix_r, pixbuf => 0); +my $text_r = Gtk2::CellRendererText->new; +$connections_combo->pack_start($text_r, 1); +$connections_combo->add_attribute($text_r, text => 1); + +my $pixbuf_size = 32; +my $empty_pixbuf = Gtk2::Gdk::Pixbuf->new('rgb', 1, 8, $pixbuf_size, $pixbuf_size); +$empty_pixbuf->fill(0); + +sub update_connections_list() { + $model->set($model->append, 0, $empty_pixbuf , 1, N("No device found")) unless @connections; + $model->set($model->append, + 0, gtknew('Pixbuf', file => $_->get_type_icon)->scale_simple($pixbuf_size, $pixbuf_size, 'hyper'), + 1, $_->get_description) foreach @connections; + my $index = $connection && eval { find_index { $_ == $connection } @connections }; + $connections_combo->set_active($index) if defined $index; +} -my $wireless_device = detect_devices::get_wireless_interface(); +sub get_connection() { + @connections or return; + my $index = $connections_combo->get_active; + defined $index && $connections[$index]; +} -unless ($wireless_device) { - ugtk2::err_dialog(N("Error"), N("You do not have any wireless interface. -Run the \"%s\" assistant from the Mandriva Linux Control Center", N("Set up a new network interface (LAN, ISDN, ADSL, ...)"))); - ugtk2::exit(0) if !$::testing; +sub prepare_connection() { + my @packages = $connection->can('get_packages') ? $connection->get_packages : (); + if (@packages && !$in->do_pkgs->install(@packages)) { + $in->ask_warn(N("Error"), N("Could not install the packages (%s)!", join(', ', @packages))); + return; + } + $connection->prepare_device; + $connection->setup_thirdparty($in) or return; + if ($connection->can("check_device") && !$connection->check_device) { + $in->ask_warn(N("Error"), $connection->{device}{error}); + return; + } + if ($connection->can('get_hardware_settings')) { + $connection->guess_hardware_settings if $connection->can('guess_hardware_settings'); + $in->ask_from_({ + title => "Network settings", + messages => N("Please enter settings for network") + }, $connection->get_hardware_settings) or return; + } + if ($connection->can('check_hardware')) { + my $_w = $in->wait_message('', N("Configuring device...")); + if (!$connection->check_hardware) { + $in->ask_warn(N("Error"), $connection->{hardware}{error}) if $connection->{hardware}{error}; + return; + } + } } -my $modules_conf = modules::any_conf->read; -my $dev = find { $_->[0] eq $wireless_device } network::ethernet::get_eth_cards($modules_conf); -my $wireless_module = $dev->[1]; +sub select_connection() { + $connection = get_connection(); + prepare_connection() if $connection; + update_on_connection_change(); +} + +sub update_on_connection_change() { + $buttons{refresh}->set_sensitive(to_bool($connection)); + update_networks(); +} my $net = {}; network::network::read_net_conf($net); -my $wireless_list = Gtk2::SimpleList->new( +my $networks_list = Gtk2::SimpleList->new( "AP" => "hidden", '' => "pixbuf", N("SSID") => "text", @@ -51,13 +124,39 @@ my $wireless_list = Gtk2::SimpleList->new( N("Encryption") => "text", N("Operating Mode") => "text", ); -$wireless_list->get_selection->set_mode('single'); +$networks_list->get_selection->set_mode('single'); + +my $status_bar = Gtk2::Statusbar->new; +my $status_bar_cid = $status_bar->get_context_id("Network event"); + +sub get_network_event_message { + my ($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); + } +} -my ($dbus, $monitor); +my $dbus; eval { $dbus = dbus_object::system_bus() }; -eval { $monitor = network::monitor->new($dbus) } if $dbus; -my $wireless_networks = {}; -my $has_roaming; +if ($dbus) { + eval { $net->{monitor} = network::monitor->new($dbus) }; + $dbus->{connection}->add_filter(sub { + my ($_con, $msg) = @_; + my $member = $msg->get_member; + my $message = get_network_event_message($member, $msg->get_args_list) or return; + my $m_id = $status_bar->push($status_bar_cid, $message); + Glib::Timeout->add(20000, sub { $status_bar->remove($status_bar_cid, $m_id); 0 }); + update_networks() if $member eq 'status'; + }); + $dbus->{connection}->add_match("type='signal',interface='com.mandriva.network'"); + dbus_object::set_gtk2_watch_helper($dbus); +} my %pixbufs = ( @@ -65,174 +164,176 @@ my %pixbufs = link_level => { map { $_ => gtkcreate_pixbuf('wifi-' . sprintf('%03d', $_) . '.png')->scale_simple(24, 24, 'hyper'); } qw(20 40 60 80 100) }, - keyring => gtkcreate_pixbuf("/usr/share/pixmaps/keyring-small.png")->scale_simple(24, 24, 'hyper'), #- provided by usermode, required by drakxtools + encryption => { map { + $_ => gtkcreate_pixbuf("encryption-$_-24.png"); + } qw(open weak strong) }, ); sub update_networks() { - ($wireless_networks, $has_roaming) = network::monitor::list_wireless($monitor, $wireless_device); - @{$wireless_list->{data}} = (); - - my $routes = network::tools::get_routes(); - my $connected = exists $routes->{$wireless_device}{network}; - - while (my ($ap, $network) = each(%$wireless_networks)) { - push @{$wireless_list->{data}}, [ - $ap, - $network->{current} ? $connected ? $pixbufs{state}{connected} : $pixbufs{state}{refresh} : undef, - $network->{essid} || exists $net->{wireless}{$ap} && $net->{wireless}{$ap}{WIRELESS_ESSID} || "[$ap]", - $pixbufs{link_level}{$network->{approx_level}}, - $network->{flags} ? $pixbufs{keyring} : undef, - $network->{flags}, - $network->{mode}, - ]; + @{$networks_list->{data}} = (); + + if ($connection) { + my $wait = $connection->network_scan_is_slow && $in->wait_message('', N("Scanning for networks...")); + $connection->{networks} = $connection->get_networks; + undef $wait; + + $connection->{network} ||= find { $connection->{networks}{$_}{current} } keys %{$connection->{networks}}; + + my $routes = network::tools::get_routes(); + my $interface = $connection->get_interface; + my $connected = exists $routes->{$interface}{network}; + + while (my ($ap, $network) = each(%{$connection->{networks}})) { + push @{$networks_list->{data}}, [ + $ap || $network->{name}, + $network->{current} ? $connected ? $pixbufs{state}{connected} : $pixbufs{state}{refresh} : undef, + !$network->{essid} && exists $net->{wireless}{$ap} && $net->{wireless}{$ap}{WIRELESS_ESSID} || $network->{name}, + network::signal_strength::get_strength_icon($network), + $pixbufs{encryption}{$network->{flags} =~ /WPA/i ? 'strong' : $network->{flags} =~ /WEP/i ? 'weak' : 'open'}, + $network->{flags}, + $network->{mode}, + ]; + } + + if ($connection->{network}) { + my $index = eval { find_index { $_->[0] eq $connection->{network} } @{$networks_list->{data}} }; + $networks_list->select($index) if defined $index; + } } - 1; -} -sub configure_ap { - my ($ap) = @_; - my $network = $wireless_networks->{$ap}; - my $essid = $network->{essid}; - my $wireless_net = - $essid && exists $net->{wireless}{$essid} ? - $net->{wireless}{$essid} : - exists $net->{wireless}{$ap} ? - $net->{wireless}{$ap} : - {}; - $wireless_net->{WIRELESS_ESSID} = $essid if $essid; + update_on_network_change(); +} - my ($wireless_enc_mode, $wireless_enc_key, $wireless_restricted); - ($wireless_enc_key, $wireless_restricted) = network::wireless::get_wep_key_from_iwconfig($wireless_net->{WIRELESS_ENC_KEY}); - $wireless_enc_mode = $network->{flags} =~ /wpa/i ? 'wpa-psk' : $network->{flags} =~ /wep/i ? $wireless_restricted ? 'restricted' : 'open' : 'none'; +sub load_settings() { + $connection->load_interface_settings; + $connection->guess_network_access_settings if $connection->can('guess_network_access_settings'); + $connection->guess_protocol($net) if $connection->can('guess_protocol'); + $connection->guess_access_settings if $connection->can('guess_access_settings'); + $connection->guess_address_settings if $connection->can('guess_address_settings'); + $connection->guess_hostname_settings if $connection->can('guess_hostname_settings'); + $connection->guess_network_control_settings if $connection->can('guess_network_control_settings'); + $connection->guess_control_settings; +} - my $dhcp = to_bool(!exists($wireless_net->{BOOTPROTO}) || $wireless_net->{BOOTPROTO} eq "dhcp"); +sub configure_network() { + load_settings(); $in->ask_from_({ - title => "Wireless settings", - messages => N("Please enter settings for wireless network \"%s\"", $essid || $ap) + title => "Network settings", + messages => N("Please enter settings for network") }, [ - { label => N("Network name (ESSID)"), val => \$wireless_net->{WIRELESS_ESSID}, disabled => sub { $essid } }, - { label => N("Encryption mode"), val => \$wireless_enc_mode, - list => [ keys %network::wireless::wireless_enc_modes ], - sort => 1, - format => sub { translate($network::wireless::wireless_enc_modes{$_[0]}) } }, - { label => N("Encryption key"), val => \$wireless_enc_key, disabled => sub { $wireless_enc_mode eq 'none' } }, - { text => N("Automatic IP (BOOTP/DHCP)"), val => \$dhcp, type => 'bool' }, - { label => N("IP address"), val => \$wireless_net->{IPADDR}, disabled => sub { $dhcp } }, - { label => N("DNS server"), val => \$wireless_net->{MS_DNS1}, disabled => sub { $dhcp } }, - { label => N("Gateway IP address"), val => \$wireless_net->{GATEWAY}, disabled => sub { $dhcp } }, + $connection->can('get_network_access_settings') ? ( + { label => $connection->get_network_access_settings_label, title => 1, advanced => 1 }, + @{$connection->get_network_access_settings}, + ) : (), + $connection->can('get_protocols') ? ( + @{$connection->get_protocol_settings}, + ) : (), + $connection->can('get_access_settings') ? ( + { label => $connection->get_access_settings_label, title => 1, advanced => 1 }, + @{$connection->get_access_settings} + ) : (), + $connection->can('get_address_settings') ? ( + { label => $connection->get_address_settings_label, title => 1, advanced => 1 }, + @{$connection->get_address_settings('show_all')} + ) : (), + $connection->can('get_network_control_settings') ? ( + @{$connection->get_network_control_settings} + ) : (), ], ) or return; - $wireless_net->{BOOTPROTO} = $dhcp ? 'dhcp' : 'static'; - $wireless_net->{WIRELESS_ENC_KEY} = $wireless_enc_key && network::wireless::convert_wep_key_for_iwconfig($wireless_enc_key, $wireless_enc_mode eq 'restricted'); - $wireless_net->{WIRELESS_MODE} = $network->{mode} eq 'Ad-Hoc' ? $network->{mode} : 'Managed'; - - if ($has_roaming || $wireless_enc_mode eq 'wpa-psk') { - $wireless_net->{WIRELESS_WPA_DRIVER} = network::wireless::wpa_supplicant_get_driver($wireless_module); - network::wireless::wpa_supplicant_add_network($wireless_net->{WIRELESS_ESSID}, $wireless_enc_mode, $wireless_enc_key); - } else { - delete $wireless_net->{WIRELESS_WPA_DRIVER}; - } - - my $ssid = $essid || $ap; - $net->{wireless}{$ssid} = $wireless_net; + $connection->install_packages($in) if $connection->can('install_packages'); + $connection->unload_connection if $connection->can('unload_connection'); - network::network::write_wireless_conf($ssid, $wireless_net); - - if ($has_roaming) { - #- this should be handled by the monitoring daemon instead - run_program::run('/usr/sbin/wpa_cli', 'reconfigure'); - } else { - overwrite_wireless_ifcfg($wireless_net); - } + my $modules_conf = modules::any_conf->read; + $connection->write_settings($net, $modules_conf); + $modules_conf->write; 1; } -sub overwrite_wireless_ifcfg { - my ($wireless_net) = @_; - my $ifcfg = $net->{ifcfg}{$wireless_device} ||= {}; - delete $ifcfg->{$_} foreach grep { /wireless/i } keys %$ifcfg; - put_in_hash($ifcfg, $wireless_net); - network::network::write_interface_conf($net, $wireless_device); -} - -sub wait_and_run_sub { - my ($time, $sub) = @_; - gtkset_mousecursor_wait(); - Glib::Timeout->add($time, sub { - $sub->(); - gtkset_mousecursor_normal(); - 0; - }); -} - -sub connect_to_ap { - my ($ap, $o_disable_configure) = @_; - my $network = $wireless_networks->{$ap}; - my $found; - - if ($network) { - my $wireless_net = !$has_roaming && ($net->{wireless}{$ap} || $net->{wireless}{$network->{essid}}); - if (defined $network->{id}) { - eval { $monitor->select_network($network->{id}) }; - $found = !$@; - $found or ugtk2::err_dialog(N("Wireless connection"), N("Unable to contact daemon")); - } elsif ($wireless_net) { - network::tools::stop_interface($wireless_device, 0); - overwrite_wireless_ifcfg($wireless_net); - network::tools::start_interface($wireless_device, 1); - $found = 1; +sub connect_to_network() { + if ($connection->selected_network_is_configured || configure_network()) { + gtkset_mousecursor_wait($w->{window}->window); + my $_wait = $in->wait_message(N("Please wait"), N("Connecting...")); + #- settings have to be rewritten only if they are impacted by choices from the main window + if ($connection->can('get_networks')) { + load_settings(); + $connection->write_settings($net); } + $connection->prepare_connection if $connection->can('prepare_connection'); + $connection->disconnect; + $connection->connect($in, $net); + gtkset_mousecursor_normal($w->{window}->window); } +} - $found || !$o_disable_configure or return; - - if (!$found) { - if ($has_roaming) { - configure_ap($ap); - #- wait for wpa_supplicant to reconfigure the device - wait_and_run_sub(2000, sub { connect_to_ap($ap, 1) }); - return; - } else { - network::tools::stop_interface($wireless_device, 0); - configure_ap($ap); - network::tools::start_interface($wireless_device, 0); - } +sub select_network() { + if ($connection) { + my ($selected) = $networks_list->get_selected_indices; + $connection->{network} = defined $selected && $networks_list->{data}[$selected][0]; } - wait_and_run_sub(10000, \&update_networks); + update_on_network_change(); } -sub configure_selected() { - my ($selected) = $wireless_list->get_selected_indices or return; - configure_ap($wireless_list->{data}[$selected][0]); +sub update_on_network_change() { + $buttons{connect}->set_label(toggle_would_disconnect() ? N("Disconnect") : N("Connect")); + #- always allow to disconnect if connected + $buttons{connect}->set_sensitive($connection && ($connection->get_status || $connection->{network})); + #- allow to configure only if a network is selected + $buttons{configure}->set_sensitive($connection && $connection->{network}); } -sub connect_to_selected() { - my ($selected) = $wireless_list->get_selected_indices or return; - connect_to_ap($wireless_list->{data}[$selected][0]); +sub toggle_would_disconnect() { + my $network = $connection && $connection->get_selected_network; + $connection && $connection->get_status && + (!$network || keys(%{$connection->{networks}}) <= 1 || $network->{current}); } -update_networks(); +sub toggle_connection() { + if (toggle_would_disconnect()) { + gtkset_mousecursor_wait($w->{window}->window); + my $_wait = $in->wait_message(N("Please wait"), N("Disconnecting...")); + $connection->disconnect; + gtkset_mousecursor_normal($w->{window}->window); + } elsif ($connection) { + $connection->{network} or return; + connect_to_network(); + } + update_on_network_change(); +} -my $w = ugtk2->new(N("Wireless connection")); gtkadd($w->{window}, gtknew('VBox', spacing => 5, children => [ - $::isEmbedded ? () : (0, Gtk2::Banner->new('/usr/share/mcc/themes/default/drakroam-mdk.png', N("Wireless connection"))), - 1, gtknew('HBox', spacing => 5, children => [ - 1, gtknew('ScrolledWindow', width => 500, height => 300, child => $wireless_list), - 0, gtknew('VButtonBox', layout => 'edge', children_loose => [ - gtknew('Button', text => N("Configure"), clicked => \&configure_selected), - gtknew('Button', text => N("Connect"), clicked => \&connect_to_selected), - gtknew('Button', text => N("Refresh"), clicked => \&update_networks), + $::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($connections_combo, changed => \&select_connection) ]), + 1, gtknew('ScrolledWindow', width => 500, height => 300, child => $networks_list), + 0, gtknew('HButtonBox', layout => 'edge', children_loose => [ + $buttons{configure} = gtknew('Button', text => N("Configure"), clicked => \&configure_network), + $buttons{connect} = gtknew('Button', relief => 'half', clicked => \&toggle_connection), + $buttons{refresh} = gtknew('Button', text => N("Refresh"), clicked => \&update_networks), gtknew('Button', text => N("Quit"), clicked => sub { Gtk2->main_quit }) - ]), ]), + 0, $status_bar, ]), ); +$networks_list->get_selection->signal_connect('changed' => \&select_network); + +$w->show; -$arg_ap and Glib::Timeout->add(100, sub { connect_to_ap($arg_ap); 0 }); +@connections = map { $_->get_connections(automatic_only => 1) } @connection_types; +$connection = $args{interface} && find { $_->get_interface eq $args{interface} } @connections; +$connection ||= find { !$_->network_scan_is_slow } @connections; +update_connections_list(); +update_on_connection_change(); + +if ($args{ap} && $connection) { + $connection->{network} = $args{ap}; + $w->{window}->show_all; + connect_to_network(); +} $w->main; diff --git a/bin/draksambashare b/bin/draksambashare index bd29dfc..e747d66 100755 --- a/bin/draksambashare +++ b/bin/draksambashare @@ -1,6 +1,7 @@ #!/usr/bin/perl +# -*- coding: utf-8 -*- # -# Copyright (C) 2005 by Mandriva aginies _ateuh_ mandriva.com +# Copyright (C) 2006 by Mandriva aginies _ateuh_ mandriva.com # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -19,16 +20,18 @@ my $version = "0.2"; +use utf8; use strict; use lib qw(/usr/lib/libDrakX); use standalone; use common; use network::network; use interactive; -use ugtk2 qw(:ask :wrappers :create :dialogs); use mygtk2 qw(gtknew); +use ugtk2 qw(:ask :wrappers :create :dialogs); use Gtk2::SimpleList; use Gtk2::Gdk::Keysyms; +use run_program; # use libconf use Libconf::Templates; @@ -130,7 +133,7 @@ sub sort_by_column { #path comment browseable printable print command guest ok writable write list inherit permissions printing lpq command create mode use client driver -my $samba = new Libconf::Glueconf::Samba::Smb_conf({ filename => '/etc/samba/smb.conf'}); +my $samba = Libconf::Glueconf::Samba::Smb_conf->new({ filename => '/etc/samba/smb.conf' }); my (@listshare, @listprinters, @listusers); my @yesno = qw(yes no); push @yesno, ""; my @default_case = qw(upper lower); push @default_case, ""; @@ -151,20 +154,39 @@ my %adv_options = ( inherit_permissions => N("Inherit permissions"), ); +my $window; + sub get_items() { my @items = ( - [ "/_File", undef, undef, undef, '<Branch>', ], - [ "/_File/_Write conf", undef, \&write_conf, 1, '<StockItem>', 'gtk-execute' ], - [ "/_File/_Exit", undef, \&quit_all, 1, '<StockItem>', 'gtk-quit' ], - - [ "/_Samba Server", undef, undef, undef, '<Branch>', ], - [ "/_Samba Server/_Restart", undef, \&restart_dialog, 1, '<StockItem>', 'gtk-execute' ], - [ "/_Samba Server/R_eload", undef, \&reload_dialog, 1, '<StockItem>', 'gtk-refresh' ], - - [ "/_About/Report a bug", undef, sub { unless (fork()) { exec("drakbug --report draksambashare &") } }, 1, '<StockItem>', 'gtk-stop' ], - [ "/_About/About...", undef, sub { - create_dialog(N("About Draksambashare"), N("Mandriva Linux \nRelease: %s\nAuthor: Antoine Ginies\n\nThis is a simple tool to easily manage Samba configuration.", $version)); - }, 1, '<StockItem>', 'gtk-preferences' ], + [ N("/_File"), undef, undef, undef, '<Branch>', ], + [ N("/_File") . N("/_Write conf"), undef, \&write_conf, 1, '<Item>', ], + [ N("/_File") . N("/_Quit"), N("<control>Q"), \&quit_all, 1, '<Item>', ], + + [ N("/_Samba Server"), undef, undef, undef, '<Branch>', ], + [ N("/_Samba Server") . N("/_Restart"), undef, \&restart_dialog, 1, '<Item>', ], + [ N("/_Samba Server") . N("/R_eload"), undef, \&reload_dialog, 1, '<Item>', ], + + [ N("/_About") . N("/_Report Bug"), undef, sub { run_program::raw({ detach => 1 }, 'drakbug', '--report', 'draksambashare') }, 1, '<Item>', ], + [ N("/_About") . N("/About..."), undef, sub { + my $license = formatAlaTeX(translate($::license)); + $license =~ s/\n/\n\n/sg; # nicer formatting + my $w = gtknew('AboutDialog', name => N("Draksambashare"), + version => '2007', + copyright => N("Copyright (C) %s by Mandriva", '2001-2006'), + license => $license, wrap_license => 1, + comments => N("This is a simple tool to easily manage Samba configuration."), + website => 'http://mandrivalinux.com', + website_label => N("Mandriva Linux"), + authors => 'Antoine Ginies <aginies@mandriva.com>', + artists => 'Hélène Durosini <ln@mandriva.com>', + translator_credits => + #-PO: put here name(s) and email(s) of translator(s) (eg: "John Smith <jsmith@nowhere.com>") + N("_: Translator(s) name(s) & email(s)\n"), + transient_for => $window->{real_window}, modal => 1, position_policy => 'center-on-parent', + ); + $w->show_all; + $w->run; + }, 1, '<Item>', ], ); return @items; } @@ -183,7 +205,7 @@ sub reload_dialog() { sub wait_action { my ($cmd) = @_; - my $w = $in->wait_message(N("Samba server"), N("Restarting/Reloading Samba server...")); + my $w = $in->wait_message(N("Please wait"), N("Restarting/Reloading Samba server...")); run_program::get_stdout($cmd) !~ /unknown|error/ or err_dialog(N("Error!"), N("Error Restarting/Reloading Samba server")) and return; undef $w; } @@ -288,61 +310,17 @@ sub write_conf() { $samba->write_conf("/etc/samba/smb.conf"); } -sub create_pango_help_box { - # perl code from draksec - my ($help) = @_; - my $text = Gtk2::TextView->new; - use Gtk2::Pango; - my %common_opts = ('left-margin' => '10', 'right-margin' => '10'); - gtktext_insert($text, [ map { - if (s!^/span>!!) { - [ $_, \%common_opts ]; - } elsif (s!span !!) { - my %tags = %common_opts; - while (s!(\w+?)="(\w+?)"!!) { - $tags{weight} ||= Gtk2::Pango->PANGO_WEIGHT_BOLD if $1 eq 'foreground'; - $tags{$1} = $2 eq "bold" ? Gtk2::Pango->PANGO_WEIGHT_BOLD : $2; - } - s/^>//; - [ $_, \%tags ]; - } else { - [ $_, \%common_opts ]; - } - } split("<", formatAlaTeX($help)) ]); - gtkset_size_request(create_scrolled_window($text), 350, 300); -} - -sub help_b { - my ($help_data) = @_; - gtksignal_connect(new Gtk2::Button->new_from_stock('gtk-dialog-info'), clicked => sub { - my $dialog = _create_dialog(); - $dialog->set_transient_for($::main_window); - $dialog->set_title(N("Help")); - $dialog->set_modal(1); - gtkpack_($dialog->vbox, - 1, create_pango_help_box($help_data), - 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-close'), clicked => sub { - $dialog->destroy; - } - ), - ); - $dialog->show_all; - } - ); -} sub printdollar_section() { - $samba->{'print$'}; $samba->{'print$'}{browseable} = "yes"; $samba->{'print$'}{path} = "/var/lib/samba/printers"; $samba->{'print$'}{browseable} = "yes"; - $samba->{'print$'}{'write list'} = "\@adm root"; + $samba->{'print$'}{'write list'} = '@adm root'; $samba->{'print$'}{'guest ok'} = "yes"; $samba->{'print$'}{'inherit permissions'} = "yes"; } sub pdf_section() { - $samba->{'pdf-gen'}; $samba->{'pdf-gen'}{path} = "/var/tmp"; $samba->{'pdf-gen'}{'guest ok'} = "no"; $samba->{'pdf-gen'}{printable} = "yes"; @@ -353,7 +331,6 @@ sub pdf_section() { } sub printers_section() { - $samba->{printers}; $samba->{printers}{comment} = "All Printers"; $samba->{printers}{browseable} = "no"; $samba->{printers}{'guest ok'} = "yes"; @@ -366,71 +343,70 @@ sub printers_section() { } sub add_entry() { - require wizards; - my ($wiz_addshare_name, $wiz_addshare_comment, $wiz_addshare_path); - my $wiz = wizards->new({ - name => N("Add a Samba share"), - pages => { - welcome => { - name => N("Goal of this wizard is to easily create a new Samba share."), - data => [ - { label => N("Name of the share:"), val => \$wiz_addshare_name }, - { label => N("Comment:"), val => \$wiz_addshare_comment }, - { label => N("Path:"), val => \$wiz_addshare_path }, - ], - complete => sub { - foreach my $clef (keys %$samba) { - if ($clef =~ /$wiz_addshare_name/) { - err_dialog(N("Error"), N("Share with the same name already exist or share name empty, please choose another name.")) and return 'welcome'; - } - } - if (!$wiz_addshare_path) { - err_dialog(N("Error"), N("Can't create the directory, please enter a correct path.")) and return 'welcome'; - } - if (!$wiz_addshare_comment) { - err_dialog(N("Error"), N("Please enter a Comment for this share.")) and return 'welcome'; - } - if (! -d $wiz_addshare_path) { - mkdir_p($wiz_addshare_path) or err_dialog(N("Error"), N("Can't create the directory, please enter a correct path.")) and return 'welcome'; - } - }, - post => sub { - push @{$share_list->{data}}, [ - $pixbuf_file, - $wiz_addshare_name, - $wiz_addshare_path, - $wiz_addshare_comment, - ]; - my $share = $wiz_addshare_name; - # update listshare - push @listshare, { - share_name => $share, - path => $wiz_addshare_path, - comment => $wiz_addshare_comment, - }; - # update samba conf - $samba->{$share}; - $samba->{$share}{path} = $wiz_addshare_path; - $samba->{$share}{comment} = $wiz_addshare_comment; - return; - }, - no_back => 1, - next => 'end_add', - }, - end_add => { - name => N("Congratulations"), - data => [ { label => N("The wizard successfully added the Samba share. Now just double click on it in treeview to modify it") } ], - no_back => 1, - end => 1, - next => 0, - }, - } - }); - $wiz->process($in); - $::isWizard = 0; - gtkset_mousecursor_normal(); + my ($addshare_name, $addshare_comment, $addshare_dir); + $_ = Gtk2::Entry->new foreach $addshare_name, $addshare_comment, $addshare_dir; + my $file_dialog = $fdwidget->($addshare_dir, ""); + my $button = Gtk2::Button->new(N("Open")); + $button->signal_connect(clicked => sub { $file_dialog->show }); + + my $dialog = _create_dialog(N("DrakSamba add entry"), { transient_for => $::main_window, modal => 1 }); + local $::main_window = $dialog; + + gtkpack_($dialog->vbox, + 0, gtkadd(Gtk2::Frame->new(N("Add a share")), + gtkpack_(gtkset_border_width(Gtk2::VBox->new, 3), + 0, gtkpack_(gtkset_border_width(Gtk2::VBox->new, 1), + 0, $label_and_widgets->(N("Name of the share:"), $addshare_name, ""), + 0, $label_and_widgets->(N("Comment:"), $addshare_comment, ""), + 0, $label_and_widgets->(N("Directory:"), $addshare_dir, $button), + ), + 0, gtkpack_(gtkset_border_width(Gtk2::VBox->new, 1), + 0, create_okcancel({ + cancel_clicked => sub { $dialog->destroy }, + ok_clicked => sub { + my $share = $addshare_name->get_text; + my $comment = $addshare_comment->get_text; + my $test_dir = $addshare_dir->get_text; + foreach my $clef (keys %$samba) { + if ($clef =~ /$share/) { + err_dialog(N("Error"), N("Share with the same name already exist or share name empty, please choose another name.")) and return; + } + } + if ($share ne 'homes' && !-d $test_dir) { + err_dialog(N("Error!"), N("Please enter a directory to share.")) and return; + } + if (! -d $test_dir) { + mkdir_p($test_dir) or err_dialog(N("Error"), N("Can't create the directory, please enter a correct path.")) and return; + } + if (! $comment) { + err_dialog(N("Error"), N("Please enter a Comment for this share.")) and return; + } + push @{$share_list->{data}}, [ + $pixbuf_file, + $share, + $test_dir, + $comment, + ]; + # update listshare + push @listshare, { + share_name => $share, + path => $test_dir, + comment => $comment, + }; + # update samba conf + $samba->{$share}{path} = $test_dir; + $samba->{$share}{comment} = $comment; + $dialog->destroy; + } + } + ), + ), + ), + ), + ); + $dialog->show_all; } - + sub add_printers_entry() { require wizards; my %print = ( @@ -446,7 +422,6 @@ sub add_printers_entry() { data => [ { label => "", type => 'list', val => \$wiz_todo, list => [ keys %print ], format => sub { $print{$_[0]} } } ], - no_back => 1, next => 'end_add', post => sub { if ($wiz_todo == 1) { @@ -532,9 +507,16 @@ sub add_printers_entry() { }, } }); - $wiz->process($in); + eval { $wiz->process($in) }; + my $err = $@; $::isWizard = 0; + $::WizardWindow->destroy; + undef $::WizardTable; + undef $::WizardWindow; # gtkset_mousecursor_normal() + if ($err && $err !~ /wizcancel/) { + err_dialog(N("Error"), N("Failed to add printers.") . "\n\n" . $err); + } } sub modify_printers_entry { @@ -564,16 +546,12 @@ sub modify_printers_entry { $use_client_driver->set_text($printer_list->{data}[$selected][14]); my $file_dialog = $fdwidget->($dir, ""); - my $button = Gtk2::Button->new_from_stock('gtk-open'); + my $button = Gtk2::Button->new(N("Open")); $button->signal_connect(clicked => sub { $file_dialog->show }); - my $dialog = _create_dialog(); - $dialog->set_transient_for($::main_window); + my $dialog = _create_dialog(N("DrakSamba Printers entry"), { transient_for => $::main_window, modal => 1 }); + local $::main_window = $dialog; - $dialog->set_title("DrakSamba Printers entry"); - $dialog->set_position('center'); - $dialog->set_modal(1); - $dialog->set_resizable(1); if ($s eq "printers") { $printable->set_text("yes"); $printing->set_text(""); @@ -689,7 +667,7 @@ sub modify_entry { $_->set_popdown_strings(@yesno) foreach $browseable, $public, $writable, $hide_dot_files, $preserve_case, $inherit_permissions; my $file_dialog = $fdwidget->($dir, ""); - my $button = Gtk2::Button->new_from_stock('gtk-open'); + my $button = Gtk2::Button->new(N("Open")); $button->signal_connect(clicked => sub { $file_dialog->show }); my $w = ugtk2->new(N("DrakSamba entry")); @@ -792,7 +770,7 @@ sub modify_entry { my $share = $share_name->get_text; my $test_dir = $dir->get_text; $comment->get_text or err_dialog(N("Information"), N("Please enter a Comment for this share.")) and return 1; - if ($share !~ /^homes$/ and !-d $test_dir) { + if ($share ne 'homes' && !-d $test_dir) { err_dialog(N("Error!"), N("Please enter a directory to share.")) and return; } foreach ($create_mask->get_text, $directory_mask->get_text) { @@ -803,7 +781,7 @@ sub modify_entry { foreach ($read_list->get_text, $write_list->get_text, $admin_users->get_text, $valid_users->get_text) { my @users = split(" ", $_); foreach my $user (@users) { - if (!any { /^$user:/ } cat_("/etc/samba/smbpasswd") and !/\@/) { + if (!(any { /^$user:/ } cat_("/etc/samba/smbpasswd")) && !/\@/) { err_dialog(N("Error"), N("Please create this Samba user: %s", $user)) and return; } } @@ -899,20 +877,16 @@ sub remove_user { sub get_user() { my $conf = "/etc/passwd"; - my @data; local $_; - foreach (cat_($conf)) { - push @data, $1 if m/^([^#:]+):[^:]+:([^:]+):/ and $2 > 499; - } - push @data, " "; - return sort(@data); + my @data = map { if_(m/^([^#:]+):[^:]+:([^:]+):/ && $2 > 499, $1) } cat_($conf); + return sort(@data, " "); } sub modify_user_info { - my ($user, $passwd, $todo) = @_; + my ($user, $_passwd, $todo) = @_; my ($buser, $bpasswd); my $dialog = new Gtk2::Dialog(); - $dialog->set_title("Add Samba user"); + $dialog->set_title(N("Add Samba user")); $dialog->set_modal(1); $dialog->set_position('center'); $dialog->set_resizable(0); @@ -1043,7 +1017,8 @@ add_data_printer_list($printer_list); add_data_user_list($user_list); $_->set_rules_hint(1) foreach $share_list, $printer_list, $user_list; -my $window = ugtk2->new("DrakSamba"); +$ugtk2::wm_icon = $fileshare_icon; +$window = ugtk2->new(N("Manage Samba configuration")); $::main_window = $window->{real_window}; $window->{rwindow}->set_size_request(600, 410) unless $::isEmbedded; $window->{rwindow}->set_position('center') if !$::isEmbedded; @@ -1085,7 +1060,7 @@ my $menuitem1 = Gtk2::MenuItem->new(N("Modify")); my $menuitem2 = Gtk2::MenuItem->new(N("Remove")); $menuitem1->signal_connect(activate => sub { my ($selected) = $share_list->get_selected_indices; - modify_entry($selected, $share_list); + modify_entry($selected); }); $menuitem2->signal_connect(activate => sub { my ($selected) = $share_list->get_selected_indices; @@ -1095,17 +1070,17 @@ $menuitem2->signal_connect(activate => sub { $_->show foreach $menuitem1, $menuitem2; $menupopup->append($_) foreach $menuitem1, $menuitem2; $share_list->signal_connect('button-press-event' => sub { - my ($widget, $event) = @_; + my (undef, $event) = @_; return unless $event->button == 3; $menupopup->popup(undef, undef, undef, undef, $event->button, $event->time); } ); $share_list->signal_connect(key_press_event => sub { - my ($widget, $event) = @_; + my (undef, $event) = @_; return unless $event->keyval == $Gtk2::Gdk::Keysyms{Return}; my ($selected) = $share_list->get_selected_indices; - modify_entry($selected, $share_list); + modify_entry($selected); return 1; }); @@ -1124,19 +1099,11 @@ my $okcancel = create_okcancel({ gtkappend_page(my $nb = Gtk2::Notebook->new, gtkpack_(gtkset_border_width(Gtk2::HBox->new, 0), 1, create_scrolled_window($share_list), 0, gtkpack_(create_vbox('start'), - 0, gtksignal_connect(Gtk2::Button->new(N("Add")), clicked => sub { - eval { add_entry() }; - my $err = $@; - $::WizardWindow->destroy if defined $::WizardWindow; - undef $::WizardWindow; - if ($err && $err !~ /wizcancel/) { - err_dialog(N("Error"), N("Failed to add Samba share.") . "\n\n" . $err); - } - }), + 0, gtksignal_connect(Gtk2::Button->new(N("Add")), clicked => \&add_entry), 0, Gtk2::HSeparator->new, 0, gtksignal_connect(Gtk2::Button->new(N("Modify")), clicked => sub { my ($selected) = $share_list->get_selected_indices; - eval { modify_entry($selected, $share_list) }; + eval { modify_entry($selected) }; my $err = $@; if ($err) { err_dialog(N("Error"), N("Failed to Modify Samba share.") . "\n\n" . $err); @@ -1163,15 +1130,7 @@ gtkappend_page(my $nb = Gtk2::Notebook->new, gtkpack_(gtkset_border_width(Gtk2:: gtkappend_page($nb, gtkpack_(gtkset_border_width(Gtk2::HBox->new, 0), 1, create_scrolled_window($printer_list), 0, gtkpack_(create_vbox('start'), - 0, gtksignal_connect(Gtk2::Button->new(N("Add printers")), clicked => sub { - eval { add_printers_entry() }; - my $err = $@; - $::WizardWindow->destroy if defined $::WizardWindow; - undef $::WizardWindow; - if ($err && $err !~ /wizcancel/) { - err_dialog(N("Error"), N("Failed to add printers.") . "\n\n" . $err); - } - }), + 0, gtksignal_connect(Gtk2::Button->new(N("Add")), clicked => \&add_printers_entry), 0, Gtk2::HSeparator->new, 0, gtksignal_connect(Gtk2::Button->new(N("Modify")), clicked => sub { my ($selected) = $printer_list->get_selected_indices; @@ -1202,23 +1161,23 @@ gtkappend_page($nb, gtkpack_(gtkset_border_width(Gtk2::HBox->new, 0), gtkappend_page($nb, gtkpack_(gtkset_border_width(Gtk2::HBox->new, 0), 1, create_scrolled_window($user_list), 0, gtkpack_(create_vbox('start'), - 0, gtksignal_connect(Gtk2::Button->new(N("Change password")), clicked => sub { - my ($selected) = $user_list->get_selected_indices; - eval { modify_user_info($user_list->{data}[$selected][1], "", "change") }; + 0, gtksignal_connect(Gtk2::Button->new(N("Add")), clicked => sub { + eval { modify_user_info("", "", "add") }; my $err = $@; - if ($err) { - err_dialog(N("Error"), N("Failed to change user password.") . "\n\n" . $err); + if ($err) { + err_dialog(N("Error"), N("Failed to add user.") . "\n\n" . $err); } }), 0, Gtk2::HSeparator->new, - 0, gtksignal_connect(Gtk2::Button->new(N("Add user")), clicked => sub { - eval { modify_user_info("", "", "add") }; + 0, gtksignal_connect(Gtk2::Button->new(N("Modify")), clicked => sub { + my ($selected) = $user_list->get_selected_indices; + eval { modify_user_info($user_list->{data}[$selected][1], "", "change") }; my $err = $@; - if ($err) { - err_dialog(N("Error"), N("Failed to add user.") . "\n\n" . $err); + if ($err) { + err_dialog(N("Error"), N("Failed to change user password.") . "\n\n" . $err); } }), - 0, gtksignal_connect(Gtk2::Button->new(N("Delete user")), clicked => sub { + 0, gtksignal_connect(Gtk2::Button->new(N("Remove")), clicked => sub { my ($selected) = $user_list->get_selected_indices; ask_okcancel("Remove entry ?", "Remove $user_list->{data}[$selected][1]") or return; eval { @@ -1231,6 +1190,7 @@ gtkappend_page($nb, gtkpack_(gtkset_border_width(Gtk2::HBox->new, 0), } }), 0, Gtk2::HSeparator->new, + # FIXME: Why do we have both an "add" button and a "userdrake" one ??? 0, gtksignal_connect(Gtk2::Button->new(N("Userdrake")), clicked => sub { run_program::raw({ detach => 1 }, 'userdrake'); } @@ -1248,7 +1208,7 @@ $nb->set_show_border(0); # main interface $W->add(gtkpack_(Gtk2::VBox->new(0,0), 0, $menu, - if_(!$::isEmbedded, 0, Gtk2::Banner->new('IC-winacces1-48', N("DrakSamba manage Samba shares"))), + 0, Gtk2::Banner->new('IC-winacces1-48', N("DrakSamba manage Samba shares")), #if_($::isEmbedded, 0, Gtk2::Label->new("Here you can add, remove and alter Samba shares.")), 1, $nb, 0, $okcancel, diff --git a/bin/drakvpn b/bin/drakvpn index 09ddae8..fbf10a6 100644 --- a/bin/drakvpn +++ b/bin/drakvpn @@ -1,1136 +1,17 @@ #!/usr/bin/perl -# -# author Florin Grad (florin@mandrakesoft.com) -# -# Copyright 2005 Mandriva -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2, as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# - +# drakvpn: VPN configuration GUI +# Olivier Blin, 2006 <oblin@mandriva.com> +# Licensed under the GPL +use strict; use lib qw(/usr/lib/libDrakX); -use standalone; #- warning, standalone must be loaded very first, for 'explanations' - -use common; -use detect_devices; +# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX) +BEGIN { unshift @::textdomains, 'drakx-net' } +use standalone; use interactive; -use network::network; -use log; -use c; -use network::netconnect; -use network::shorewall; -use network::ipsec; -use Data::Dumper; - -$::isInstall and die "Not supported during install.\n"; - - -local $_ = join '', @ARGV; - -$::Wizard_pix_up = "drakvpn.png"; -$ugtk2::wm_icon = "drakvpn"; - -my $direct = /-direct/; - -my ($kernel_version) = c::kernel_version() =~ /(...)/; -log::l("[drakvpn] kernel_version $kernel_version"); - -$kernel_version >= 2.4 or fatal_quit(N("Sorry, we support only 2.4 and above kernels.")); - -my $tunnels_file = "/etc/shorewall/tunnels"; -my $ipsec_conf = ""; -my $racoon_conf = "/etc/racoon/racoon.conf"; -my $proc_version = ""; -my $ipsec_package = ""; - -my $in = interactive->vnew('su'); -my $shorewall = network::shorewall::read($in); -my @section_names; - -if ($kernel_version > 2.5) { - $ipsec_conf = "/etc/ipsec.conf"; -} else { - $ipsec_conf = "/etc/freeswan/ipsec.conf"; -} -my $ipsec = network::ipsec::read_ipsec_conf($ipsec_conf,$kernel_version); -my $racoon = network::ipsec::read_racoon_conf($racoon_conf); - -#print network::ipsec::display_ipsec_conf($ipsec_conf,$ipsec,$kernel_version); - -$::Wizard_title = N("DrakVPN"); - -$in->isa('interactive::gtk') and $::isWizard = 1; - -my $wait_configuring; - -sub fatal_quit ($) { - log::l("[drakvpn] FATAL: $_[0]"); - undef $wait_configuring; - $in->ask_warn('', $_[0]); - quit_global($in, -1); -} - -begin: - -#- ********************************** -#- * 0th step: verify if we are already set up - -if ($shorewall && any { !/^\s*(?:#|\n)/ } cat_($tunnels_file)) { - $::Wizard_no_previous = 1; - - if (!$shorewall->{disabled}) { - my $r = $in->ask_from_list_(N("The VPN connection is enabled."), -N("The setup of a VPN connection has already been done. - -It's currently enabled. - -What would you like to do?"), - [ N_("disable"), N_("reconfigure"), N_("dismiss") ]) or quit_global($in, 0); - # FIXME: reconfigure is not handled - if ($r eq "disable") { - if (!$::testing) { - my $_wait_disabl = $in->wait_message('', N("Disabling VPN...")); - network::ipsec::stop_daemons(); - } - foreach ($ipsec_conf, $tunnels_file) { - if (-f $_) { rename($_, "$_.drakvpndisable") or die "Could not rename $_ to $_.drakvpndisable" } - } - network::ipsec::sys("/etc/init.d/shorewall restart >/dev/null"); - log::l("[drakvpn] Disabled"); - $::Wizard_finished = 1; - $in->ask_okcancel('', N("The VPN connection is now disabled.")); - quit_global($in, 0); - } - if ($r eq "dismiss") { - quit_global($in, 0); - } - } else { - my $r = $in->ask_from_list_(N("VPN connection currently disabled"), -N("The setup of a VPN connection has already been done. - -It's currently disabled. - -What would you like to do?"), - [ N_("enable"), N_("reconfigure"), N_("dismiss") ]); - # FIXME: reconfigure is not handled - if ($r eq "enable") { - foreach ($ipsec_conf, $tunnels_file) { - rename($_, "$_.old") if -f $_; - rename("$_.drakvpndisable", $_) or die "Could not find configuration. Please reconfigure."; - } - { - my $_wait_enabl = $in->wait_message('', N("Enabling VPN...")); - network::ipsec::start_daemons(); - } - log::l("[drakvpn] Enabled"); - } - $::Wizard_finished = 1; - $in->ask_okcancel('', N("The VPN connection is now enabled.")); - quit_global($in, 0); - if ($r eq "dismiss") { - quit_global($in, 0); - } - } - } - -#- ********************************** -#- * 1st step: detect/setup -step_ask_confirm: - -$::Wizard_no_previous = 1; - -$direct or $in->ask_okcancel(N("Simple VPN setup."), -N("You are about to configure your computer to use a VPN connection. - -With this feature, computers on your local private network and computers -on some other remote private networks, can share resources, through -their respective firewalls, over the Internet, in a secure manner. - -The communication over the Internet is encrypted. The local and remote -computers look as if they were on the same network. - -Make sure you have configured your Network/Internet access using -drakconnect before going any further."), 1) or goto begin; - -undef $::Wizard_no_previous; - -if ($kernel_version < 2.5) { - system("/sbin/modprobe ipsec") if -e "/sbin/modprobe"; - $proc_version = cat_("/proc/net/ipsec_version") if -e "/proc/net/ipsec_version"; - if ($proc_version =~ /super/i) { - $ipsec_package = "super-freeswan"; - } else { - $ipsec_package = "freeswan"; - } -} else { - $ipsec_package = "ipsec-tools"; - $proc_version = "ipsec native"; -} - -$direct or $in->ask_okcancel(N("Simple VPN setup."), -N("VPN connection. - -This program is based on the following projects: - - FreeSwan: \t\t\thttp://www.freeswan.org/ - - Super-FreeSwan: \t\thttp://www.freeswan.ca/ - - ipsec-tools: \t\t\thttp://ipsec-tools.sourceforge.net/ - - ipsec-howto: \t\thttp://www.ipsec-howto.org - - the docs and man pages coming with the %s package - -Please read AT LEAST the ipsec-howto docs -before going any further.",$ipsec_package)) or goto begin; - -$direct or $in->ask_okcancel(N("Kernel module."), -N("The kernel needs to have ipsec support. - -You're running a %s kernel version. - -This kernel has '%s' support.", $kernel_version, $proc_version)) or goto begin; - -step_detectsetup: - -#my @configured_devices = map { /ifcfg-(\S+)/ } glob('/etc/sysconfig/network-scripts/ifcfg*'); - -my %aliased_devices; -/^\s*alias\s+(eth[0-9])\s+(\S+)/ and $aliased_devices{$1} = $2 foreach cat_("/etc/modules.conf"); - -#- ********************************** -#- * 2nd step: configure - -#$wait_configuring = $in->wait_message(N("Configuring..."), -# N("Configuring scripts, installing software, starting servers...")); - -#- if the kernel has super-freeswan support, remove the freeswan package -#- and vice-versa -#- if you're using e kernel 2.5 and above with native ipsec support, remove -#- both freeswan and super-freeswan packages - -if (!$::testing && $ipsec_package =~ /super/i && $kernel_version < 2.5) { - log::l("[drakvpn] removing the freeswan package"); - $in->do_pkgs->remove("freeswan") if -e "/etc/freeswan/ipsec.d/policies/clear"; - log::l("[drakvpn] removing the ipsec-tools package"); - $in->do_pkgs->remove("ipsec-tools") if -e "/sbin/setkey"; - $in->do_pkgs->remove("libipsec-tools0") if -e "/lib/libipsec.so.0"; -} elsif (!$::testing && $kernel_version < 2.5) { - log::l("[drakvpn] removing the $ipsec_package package"); - $in->do_pkgs->remove("super-freeswan") if -e "/usr/lib/ipsec/auto.advroute"; - log::l("[drakvpn] removing the ipsec-tools package"); - $in->do_pkgs->remove("ipsec-tools") if -e "/sbin/setkey"; - $in->do_pkgs->remove("libipsec-tools0") if -e "/sbin/setkey"; -} else { - log::l("[drakvpn] removing the freeswan AND the super-freeswan packages"); - $in->do_pkgs->remove("freeswan") if -e "/etc/freeswan/ipsec.d/policies/clear"; - $in->do_pkgs->remove("super-freeswan-doc") if -e "/usr/sbin/ipsec"; - $in->do_pkgs->remove("super-freeswan") if -e "/usr/lib/ipsec/auto.advroute"; -} - - -#- install and setup the RPM packages, if needed - -my %rpm2file; -log::l("[drakvpn] install the $ipsec_package and the shorewall rpm packages"); -if (!$::testing && $ipsec_package =~ /ipsec-tools/i) { - %rpm2file = ($ipsec_package => '/sbin/setkey', - shorewall => '/sbin/shorewall'); -} else { - %rpm2file = ($ipsec_package => '/usr/sbin/ipsec', - shorewall => '/sbin/shorewall'); -} - -#- first: try to install all in one step, if needed -if (! ($ipsec_package =~ /super/i && -e "/usr/lib/ipsec/auto.advroute" || - $ipsec_package =~ /^freeswan/i && -e "/etc/freeswan/ipsec.d/policies/clear" || - $ipsec_package =~ /ipsec-tools/i && -e "/sbin/setkey")) { - - my @needed_to_install = grep { !-e $rpm2file{$_} } keys %rpm2file; - @needed_to_install and $in->do_pkgs->install(@needed_to_install) if !$::testing; - #- second: try one by one if failure detected - if (!$::testing && any { !-e $rpm2file{$_} } keys %rpm2file) { - foreach (keys %rpm2file) { - -e $rpm2file{$_} or $in->do_pkgs->install($_); - -e $rpm2file{$_} or fatal_quit(N("Problems installing package %s", $_)); - } - } -} - -undef $wait_configuring; - -#- configure the $ipsec_conf file -#- Add, Remove config|conn entries - -step_configuration: - -my $c; - -my %messages = (ipsec => N("Security Policies"), racoon => N("IKE daemon racoon")); - -if ($kernel_version > 2.5) { - $in->ask_from(N("Configuration file"), -N("Configuration step! - -You need to define the Security Policies and then to -configure the automatic key exchange (IKE) daemon. -The KAME IKE daemon we're using is called 'racoon'. - -What would you like to configure?\n"), - [ { val => \$c, type => "list", list => [ keys %messages ], format => sub { $messages{$_[0]} } } ]) or goto step_detectsetup; - -} else { -$in->ask_okcancel(N("Configuration file"), -N("Next, we will configure the %s file.\n - -Simply click on Next.\n", $ipsec_conf)) or goto step_detectsetup; - - $c = "configure"; -} - -#------------------------------------------------------------------- -#---------------------- configure ipsec_conf ----------------------- -#------------------------------------------------------------------- - -if ($c eq "ipsec" || $c eq "configure") { - -step_configure_ipsec_conf: - -@section_names = network::ipsec::get_section_names_ipsec_conf($ipsec,$kernel_version) if $ipsec; - -my $choice = $section_names[0]; -my $d = $in->ask_from_list_(N("%s entries", $ipsec_conf), -N("The %s file contents -is divided into sections.\n -You can now:\n - - display, add, edit, or remove sections, then - - commit the changes - -What would you like to do?\n", $ipsec_conf), - [ N_("_:display here is a verb\nDisplay"), N_("Add"), N_("Edit"), N_("Remove"), N_("Commit") ]) or goto step_configuration; - -my $existing_section = ""; - -#- display $ipsec_conf ------------------------- - -step_display_ipsec_conf: - -if ($d eq "display $ipsec_conf" || $d eq "_:display here is a verb\nDisplay") { - my $ipsec_exists = 0; - foreach my $key (keys %$ipsec) { - $ipsec_exists = 1 if $ipsec->{$key}; - } - if ($ipsec_exists) { - $in->ask_okcancel(N("_:display here is a verb\nDisplay configuration"), - network::ipsec::display_ipsec_conf($ipsec,$kernel_version)); - goto step_configure_ipsec_conf; - } else { -$in->ask_okcancel(N("_:display here is a verb\nDisplay configuration"), -N("The %s file does not exist.\n -This must be a new configuration.\n -You'll have to go back and choose 'add'.\n", $ipsec_conf)); - goto step_configure_ipsec_conf; - } - -#- add --------------------- - -} elsif ($d eq "Add") { - -step_add_section: - -if ($kernel_version < 2.5) { - -#- add ---- kernel 2.4 part ------------------------------- - -my $e = $in->ask_from_list_(N("ipsec.conf entries"), -N("The %s file contains different sections.\n -Here is its skeleton: 'config setup' - 'conn default' - 'normal1' - 'normal2' \n -You can now add one of these sections.\n -Choose the section you would like to add.\n", $ipsec_conf), - [ N_("config setup"), N_("conn %default"), N_("normal conn"), N_("dismiss") ]) or goto step_configure_ipsec_conf; - if ($e eq "config setup") { - - $existing_section = network::ipsec::already_existing_section_ipsec_conf("config setup", $ipsec, $kernel_version); - - if ($existing_section eq "already existing") { -$in->ask_okcancel(N("Exists!"), -N("A section with this name already exists. -The section names have to be unique.\n -You'll have to go back and add another section -or change its name.\n")); - goto step_add_section; -} - - my $config_setup = { - 1 => [ "config", "setup" ], - 2 => [ "interfaces", "%defaultroute" ], - 3 => [ "klipsdebug", "none" ], - 4 => [ "plutodebug", "none" ], - 5 => [ "plutoload", "%search" ], - 6 => [ "plutostart", "%search" ], - 7 => [ "uniqueids", "yes" ], - }; - $in->ask_from('', -N("This section has to be on top of your -%s file.\n -Make sure all other sections follow this config -setup section.\n -Choose continue or previous when you are done.\n", $ipsec_conf), - [ { label => N("interfaces"), val => \$config_setup->{2}[1], type => 'entry' }, - { label => N("klipsdebug"), val => \$config_setup->{3}[1], type => 'entry' }, - { label => N("plutodebug"), val => \$config_setup->{4}[1], type => 'entry' }, - { label => N("plutoload"), val => \$config_setup->{5}[1], type => 'entry' }, - { label => N("plutostart"), val => \$config_setup->{6}[1], type => 'entry' }, - { label => N("uniqueids"), val => \$config_setup->{7}[1], type => 'entry' }, - ] -) or goto step_configure_ipsec_conf; - - network::ipsec::add_section_ipsec_conf($config_setup, $ipsec); - - goto step_configure_ipsec_conf; - - } elsif ($e eq "conn %default") { - - $existing_section = network::ipsec::already_existing_section_ipsec_conf("conn %default", $ipsec, $kernel_version); - - if ($existing_section eq "already existing") { -$in->ask_okcancel(N("Exists!"), -N("A section with this name already exists. -The section names have to be unique.\n -You'll have to go back and add another section -or change its name.\n")); - goto step_add_section; -} - - my $conn_default = { - 1 => [ "conn", "%default" ], - 2 => [ "pfs", "yes" ], - 3 => [ "keyingtries", "1" ], - 4 => [ "compress", "yes" ], - 5 => [ "disablearrivalcheck", "no" ], - 6 => [ "left", "" ], - 7 => [ "leftcert", "" ], - 8 => [ "leftrsasigkey", "%cert" ], - 9 => [ "leftsubnet", "" ], - 10 => [ "leftnexthop", "" ], - }; - $in->ask_from('', -N("This is the first section after the config -setup one.\n -Here you define the default settings. -All the other sections will follow this one. -The left settings are optional. If do not define -them here, globally, you can define them in each -section.\n",), - [ { label => N("PFS"), val => \$conn_default->{2}[1], type => 'entry' }, - { label => N("keyingtries"), val => \$conn_default->{3}[1], type => 'entry' }, - { label => N("compress"), val => \$conn_default->{4}[1], type => 'entry' }, - { label => N("disablearrivalcheck"), val => \$conn_default->{5}[1], type => 'entry' }, - { label => N("left"), val => \$conn_default->{6}[1], type => 'entry' }, - { label => N("leftcert"), val => \$conn_default->{7}[1], type => 'entry' }, - { label => N("leftrsasigkey"), val => \$conn_default->{8}[1], type => 'entry' }, - { label => N("leftsubnet"), val => \$conn_default->{9}[1], type => 'entry' }, - { label => N("leftnexthop"), val => \$conn_default->{10}[1], type => 'entry' }, - ] -) or goto step_configure_ipsec_conf; - - network::ipsec::add_section_ipsec_conf($conn_default, $ipsec); - - goto step_configure_ipsec_conf; - - } elsif ($e eq "normal conn") { - - - my $normal_conn = { - 1 => [ "conn", "my-connection" ], - 2 => [ "authby", "rsasig" ], - 3 => [ "auto", "start" ], - 4 => [ "left", "" ], - 5 => [ "leftcert", "" ], - 6 => [ "leftrsasigkey", "%cert" ], - 7 => [ "leftsubnet", "" ], - 8 => [ "leftnexthop", "" ], - 9 => [ "right", "" ], - 10 => [ "rightcert", "" ], - 11 => [ "rightrsasigkey", "%cert" ], - 12 => [ "rightsubnet", "" ], - 13 => [ "rightnexthop", "" ], - }; - -step_add_normal_conn: - $in->ask_from('', -N("Your %s file has several sections, or connections.\n -You can now add a new section. -Choose continue when you are done to write the data.\n", $ipsec_conf), - [ { label => N("section name"), val => \$normal_conn->{1}[1], type => 'entry' }, - { label => N("authby"), val => \$normal_conn->{2}[1], type => 'entry' }, - { label => N("auto"), val => \$normal_conn->{3}[1], type => 'entry' }, - { label => N("left"), val => \$normal_conn->{4}[1], type => 'entry' }, - { label => N("leftcert"), val => \$normal_conn->{5}[1], type => 'entry' }, - { label => N("leftrsasigkey"), val => \$normal_conn->{6}[1], type => 'entry' }, - { label => N("leftsubnet"), val => \$normal_conn->{7}[1], type => 'entry' }, - { label => N("leftnexthop"), val => \$normal_conn->{8}[1], type => 'entry' }, - { label => N("right"), val => \$normal_conn->{9}[1], type => 'entry' }, - { label => N("rightcert"), val => \$normal_conn->{10}[1], type => 'entry' }, - { label => N("rightrsasigkey"), val => \$normal_conn->{11}[1], type => 'entry' }, - { label => N("rightsubnet"), val => \$normal_conn->{12}[1], type => 'entry' }, - { label => N("rightnexthop"), val => \$normal_conn->{13}[1], type => 'entry' }, - ] -) or goto step_configure_ipsec_conf; - - $existing_section = network::ipsec::already_existing_section_ipsec_conf($normal_conn->{1}[0] . " " . $normal_conn->{1}[1], $ipsec, $kernel_version); - - if ($existing_section eq "already existing") { -$in->ask_okcancel(N("Exists!"), -N("A section with this name already exists. -The section names have to be unique.\n -You'll have to go back and add another section -or change the name of the section.\n")); - goto step_add_normal_conn; -} - - network::ipsec::add_section_ipsec_conf($normal_conn, $ipsec); - - goto step_configure_ipsec_conf; - - } - -} else { - -#- add ---- kernel 2.6 part ------------------------------- - - my $section = { command => 'spdadd', - src_range => 'src_network_address', - dst_range => 'dest_network_address', - upperspec => 'any', - flag => '-P', - direction => 'in or out', - ipsec => 'ipsec', - protocol => 'esp', - mode => 'tunnel', - src_dest => 'source-destination', - level => 'require' }; - -step_add_section_ipsec_conf_k26: - - ask_info3('', -N("Add a Security Policy.\n -You can now add a Security Policy.\n -Choose continue when you are done to write the data.\n"), $section) or goto step_configure_ipsec_conf; - -# $existing_section = network::ipsec::already_existing_section_ipsec_conf($section->{src_dest}, $ipsec, $kernel_version); -# -# if ($existing_section eq "already existing") { -#$in->ask_okcancel(N("Exists!"), -#N("A section with this name already exists. -#The section names have to be unique.\n -#You'll have to go back and add another section -#or change the name of the section.\n")); -# goto step_add_section_ipsec_conf_k26; -#}; - - if (!$ipsec->{1}) { - put_in_hash($ipsec, { max(keys %$ipsec) + 1 => "#!/sbin/setkey -f" }); - put_in_hash($ipsec, { max(keys %$ipsec) + 1 => "flush;" }); - put_in_hash($ipsec, { max(keys %$ipsec) + 1 => "spdflush;" }); - } - - network::ipsec::add_section_ipsec_conf($section, $ipsec); - - @section_names = network::ipsec::get_section_names_ipsec_conf($ipsec,$kernel_version); - - goto step_configure_ipsec_conf; -} - -#- edit --------------------- - -} elsif ($d eq "Edit") { - -step_edit_ipsec_conf: -$in->ask_from(N("Edit section"), -N("Your %s file has several sections or connections.\n -You can choose here below the one you want to edit -and then click on next.\n", $ipsec_conf), - [ { val => \$choice, list => \@section_names, label => N("Section names"), sort => 0, not_edit => 0 } ]) - or goto step_configure_ipsec_conf; - -my $number = network::ipsec::matched_section_key_number_ipsec_conf($choice,$ipsec,$kernel_version); - -#- edit ---- kernel 2.4 part ------------------------------- - -if ($kernel_version < 2.5) { -if ($choice =~ /^version|block|private|clear|packet/) { - -$in->ask_okcancel(N("Can not edit!"), -N("You cannot edit this section.\n -This section is mandatory for Freeswan 2.X. -One has to specify version 2.0 on the top -of the %s file, and eventually, disable or -enable the opportunistic encryption.\n",$ipsec_conf)); - goto step_edit_ipsec_conf; - -} elsif ($choice =~ /^config setup/) { - $in->ask_from('', -N("Your %s file has several sections.\n -You can now edit the config setup section entries. -Choose continue when you are done to write the data.\n", $ipsec_conf), - -[ network::ipsec::dynamic_list($number, $ipsec) ] - -) or goto step_configure_ipsec_conf; - - goto step_configure_ipsec_conf; -} elsif ($choice =~ /^conn %default/) { - $in->ask_from('', -N("Your %s file has several sections or connections.\n -You can now edit the default section entries. -Choose continue when you are done to write the data.\n", $ipsec_conf), - -[ network::ipsec::dynamic_list($number, $ipsec) ] - -) or goto step_configure_ipsec_conf; - - goto step_configure_ipsec_conf; - -} elsif ($choice =~ /^conn/) { - - $in->ask_from('', -N("Your %s file has several sections or connections.\n -You can now edit the normal section entries.\n -Choose continue when you are done to write the data.\n", $ipsec_conf), - -[ network::ipsec::dynamic_list($number, $ipsec) ] - -) or goto step_configure_ipsec_conf; - - goto step_configure_ipsec_conf; - -} else { - - goto step_configure_ipsec_conf; - -} - -#- edit ---- kernel 2.6 part ------------------------------- - -} else { - - ask_info3('', -N("Edit a Security Policy.\n -You can now edit a Security Policy.\n -Choose continue when you are done to write the data.\n"), $ipsec->{$number}) or goto step_configure_ipsec_conf; - -goto step_configure_ipsec_conf; - -} - -#- remove --------------------- - -} elsif ($d eq "Remove") { -$in->ask_from(N("Remove section"), -N("Your %s file has several sections or connections.\n -You can choose here below the one you want to remove -and then click on next.\n", $ipsec_conf), - [ { val => \$choice, list => \@section_names, label => N("Section names"), sort => 0, not_edit => 0 } ]); - - network::ipsec::remove_section_ipsec_conf($choice,$ipsec,$kernel_version); - - @section_names = network::ipsec::get_section_names_ipsec_conf($ipsec,$kernel_version) if $ipsec; - - goto step_configure_ipsec_conf; - -#- continue and write --------------------- - -} elsif ($d eq "Commit") { - log::l("[drakvpn] Modify the $ipsec_conf file"); - network::ipsec::write_ipsec_conf($ipsec_conf, $ipsec,$kernel_version); - } -#------------------------------------------------------------------- -#---------------------- configure racoon_conf ----------------------- -#------------------------------------------------------------------- - -} elsif ($c eq "racoon") { - -step_configure_racoon_conf: - -@section_names = network::ipsec::get_section_names_racoon_conf($racoon) if $racoon; - -my $choice = $section_names[0]; -my $d = $in->ask_from_list_(N("%s entries", $racoon_conf), -N("The racoon.conf file configuration.\n -The contents of this file is divided into sections. -You can now: - - display \t\t (display the file contents) - - add \t\t (add one section) - - edit \t\t\t (modify parameters of an existing section) - - remove \t\t (remove an existing section) - - commit \t\t (writes the changes to the real file)"), - [ N_("_:display here is a verb\nDisplay"), N_("Add"), N_("Edit"), N_("Remove"), N_("Commit") ]) or goto step_configuration; - - -#- display $racoon_conf ------------------------- - -step_display_racoon_conf: - -if ($d eq "_:display here is a verb\nDisplay") { - - my $racoon_exists = 0; - foreach my $key (keys %$racoon) { - $racoon_exists = 1 if $racoon->{$key}; - } - - if ($racoon_exists) { - $in->ask_okcancel(N("_:display here is a verb\nDisplay configuration"), - network::ipsec::display_racoon_conf($racoon)); - goto step_configure_racoon_conf; - } else { -$in->ask_okcancel(N("_:display here is a verb\nDisplay configuration"), -N("The %s file does not exist\n -This must be a new configuration.\n -You'll have to go back and choose configure.\n", $racoon_conf)); - goto step_configure_racoon_conf; - } - -#- add $racoon_conf ------------------------------ - -} elsif ($d eq "Add") { - -step_add_section_racoon: - -#my $existing_section = ""; - -my $e = $in->ask_from_list_(N("racoonf.conf entries"), -N("The 'add' sections step.\n -Here below is the racoon.conf file skeleton: -\t'path' -\t'remote' -\t'sainfo' \n -Choose the section you would like to add.\n"), - [ N_("path"), N_("remote"), N_("sainfo"), N_("dismiss") ]) or goto step_configure_racoon_conf; -if ($e eq "path") { - - my $path_section = { - 1 => [ 'path', 'path_type', '"/etc/racoon/certs"' ], - }; - - $in->ask_from('', -N("The 'add path' section step.\n -The path sections have to be on top of your racoon.conf file.\n -Put your mouse over the certificate entry to obtain online help."), - [ { label => N("path type"), - val => \$path_section->{1}[1], - list => [ 'certificate', 'pre_shared_key', 'include' ], - help => -N("path include path: specifies a path to include -a file. See File Inclusion. - Example: path include '/etc/racoon' - -path pre_shared_key file: specifies a file containing -pre-shared key(s) for various ID(s). See Pre-shared key File. - Example: path pre_shared_key '/etc/racoon/psk.txt' ; - -path certificate path: racoon(8) will search this directory -if a certificate or certificate request is received. - Example: path certificate '/etc/cert' ; - -File Inclusion: include file -other configuration files can be included. - Example: include \"remote.conf\" ; - -Pre-shared key File: Pre-shared key file defines a pair -of the identifier and the shared secret key which are used at -Pre-shared key authentication method in phase 1."), -}, - { label => N("real file"), val => \$path_section->{1}[2], type => 'entry' }, - ] -) or goto step_configure_racoon_conf; - -network::ipsec::add_section_racoon_conf($path_section, $racoon); -} elsif ($e eq "remote") { - my $main_remote_section = { 1 => [ 'remote', 'address' ], - 2 => [ 'exchange_mode', 'aggressive,main' ], - 3 => [ 'generate_policy', 'on' ], - 4 => [ 'passive', 'on' ], - 5 => [ 'certificate_type', 'x509', '"my_certificate.pem"', '"my_private_key.pem"' ], - 6 => [ 'peers_certfile', '"remote.public"' ], - 7 => [ 'verify_cert', 'on' ], - 8 => [ 'my_identifier', 'asn1dn' ], - 9 => [ 'peers_identifier', 'asn1dn' ] - }; - my $proposal_remote_section = { 1 => [ 'proposal' ], - 2 => [ 'encryption_algorithm', '3des' ], - 3 => [ 'hash_algorithm', 'md5' ], - 4 => [ 'authentication_method', 'rsasig' ], - 5 => [ 'dh_group', 'modp1024' ] - }; - ask_info2('', -N("Make sure you already have the path sections -on the top of your racoon.conf file. - -You can now choose the remote settings. -Choose continue or previous when you are done.\n"), $main_remote_section, $proposal_remote_section) or goto step_configure_racoon_conf; - -network::ipsec::add_section_racoon_conf($main_remote_section, $racoon); -network::ipsec::add_section_racoon_conf($proposal_remote_section, $racoon); -} elsif ($e eq "sainfo") { - my $sainfo_section = { 1 => [ 'sainfo', 'address', '192.168.100.2', 'any', 'address', '10.0.0.2', 'any' ], - 2 => [ 'pfs_group', '1' ], - 3 => [ 'lifetime', 'time', '30', 'sec' ], - 4 => [ 'encryption_algorithm', '3des' ], - 5 => [ 'authentication_algorithm', 'hmac_sha1' ], - 6 => [ 'compression_algorithm', 'deflate' ], - }; - ask_info('', -N("Make sure you already have the path sections -on the top of your %s file. - -You can now choose the sainfo settings. -Choose continue or previous when you are done.\n", $racoon_conf), $sainfo_section) or goto step_configure_racoon_conf; - -network::ipsec::add_section_racoon_conf($sainfo_section, $racoon); -} - -@section_names = network::ipsec::get_section_names_racoon_conf($racoon) if $racoon; - -goto step_configure_racoon_conf; - -#- edit $racoon_conf ----------------------------- - -} elsif ($d eq "Edit") { -$in->ask_from(N("Edit section"), -N("Your %s file has several sections or connections. - -You can choose here in the list below the one you want -to edit and then click on next.\n", $racoon_conf), - [ { val => \$choice, list => \@section_names, label => N("Section names"), sort => 0, not_edit => 0 } ]) - or goto step_configure_racoon_conf; - -my $number = network::ipsec::matched_section_key_number_racoon_conf($choice,$racoon); - -if ($choice =~ /^remote/) { - ask_info2('', -N("Your %s file has several sections.\n - -You can now edit the remote section entries. - -Choose continue when you are done to write the data.\n", $racoon_conf), $racoon->{$number}, $racoon->{$number+2}) - or goto step_configure_racoon_conf; - -} elsif ($choice =~ /^sainfo/) { - ask_info('', -N("Your %s file has several sections. - -You can now edit the sainfo section entries. - -Choose continue when you are done to write the data.", $racoon_conf), $racoon->{$number}) or goto step_configure_racoon_conf; - -} elsif ($choice =~ /^path/) { - $in->ask_from('', -N("This section has to be on top of your -%s file.\n -Make sure all other sections follow these path -sections.\n -You can now edit the path entries. - -Choose continue or previous when you are done.\n", $racoon_conf), - [ { label => N("path_type"), val => \$racoon->{$number}{1}[1], list => [ 'certificate', 'pre_shared_key', 'include' ] }, - { label => N("real file"), val => \$racoon->{$number}{1}[2], type => 'entry' }, - ] -) or goto step_configure_racoon_conf; -} - -goto step_configure_racoon_conf; - -#- remove $racoon_conf --------------------------- - -} elsif ($d eq "Remove") { -$in->ask_from(N("Remove section"), -N("Your %s file has several sections or connections.\n -You can choose here below the one you want to remove -and then click on next.\n", $racoon_conf), - [ { val => \$choice, list => \@section_names, label => N("Section names"), sort => 0, not_edit => 0 } ]); - -my $number = network::ipsec::matched_section_key_number_racoon_conf($choice,$racoon); -network::ipsec::remove_section_racoon_conf($choice,$racoon,$number); - @section_names = network::ipsec::get_section_names_racoon_conf($racoon) if $racoon; - - goto step_configure_racoon_conf; - -#- write $racoon_conf and continue --------------- -} elsif ($d eq "Commit") { - log::l("[drakvpn] Modify the $racoon_conf file"); - network::ipsec::write_racoon_conf($racoon_conf, $racoon); -} -} - -#- start the daemons -network::ipsec::start_daemons(); - -#- bye-bye message - -undef $wait_configuring; - -$::Wizard_no_previous = 1; -$::Wizard_finished = 1; - -$in->ask_okcancel(N("Congratulations!"), -N("Everything has been configured.\n -You may now share resources through the Internet, -in a secure way, using a VPN connection. - -You should make sure that that the tunnels shorewall -section is configured.")); - -log::l("[drakvpn] Installation complete, exiting"); -quit_global($in, 0); - -sub quit_global { - my ($in, $exitcode) = @_; - $in->exit($exitcode); - goto begin; -} - - -sub ask_info { - my ($title, $text, $data) = @_; - $in->ask_from($title, $text, - [ { label => N("Sainfo source address"), val => \$data->{1}[2], type => 'entry', - help => N("sainfo (source_id destination_id | anonymous) { statements } -defines the parameters of the IKE phase 2 -(IPsec-SA establishment). - -source_id and destination_id are constructed like: - - address address [/ prefix] [[port]] ul_proto - -Examples: \n -sainfo anonymous (accepts connections from anywhere) - leave blank this entry if you want anonymous - -sainfo address 203.178.141.209 any address 203.178.141.218 any - 203.178.141.209 is the source address - -sainfo address 172.16.1.0/24 any address 172.16.2.0/24 any - 172.16.1.0/24 is the source address") }, - { label => N("Sainfo source protocol"), val => \$data->{1}[3], type => 'entry', - help => N("sainfo (source_id destination_id | anonymous) { statements } -defines the parameters of the IKE phase 2 -(IPsec-SA establishment). - -source_id and destination_id are constructed like: - - address address [/ prefix] [[port]] ul_proto - -Examples: \n -sainfo anonymous (accepts connections from anywhere) - leave blank this entry if you want anonymous - -sainfo address 203.178.141.209 any address 203.178.141.218 any - the first 'any' allows any protocol for the source") }, - { label => N("Sainfo destination address"), val => \$data->{1}[5], type => 'entry', - help => N("sainfo (source_id destination_id | anonymous) { statements } -defines the parameters of the IKE phase 2 -(IPsec-SA establishment). - -source_id and destination_id are constructed like: - - address address [/ prefix] [[port]] ul_proto - -Examples: \n -sainfo anonymous (accepts connections from anywhere) - leave blank this entry if you want anonymous - -sainfo address 203.178.141.209 any address 203.178.141.218 any - 203.178.141.218 is the destination address - -sainfo address 172.16.1.0/24 any address 172.16.2.0/24 any - 172.16.2.0/24 is the destination address") }, - { label => N("Sainfo destination protocol"), val => \$data->{1}[6], type => 'entry', - help => N("sainfo (source_id destination_id | anonymous) { statements } -defines the parameters of the IKE phase 2 -(IPsec-SA establishment). - -source_id and destination_id are constructed like: - - address address [/ prefix] [[port]] ul_proto - -Examples: \n -sainfo anonymous (accepts connections from anywhere) - leave blank this entry if you want anonymous - -sainfo address 203.178.141.209 any address 203.178.141.218 any - the last 'any' allows any protocol for the destination") }, - { label => N("PFS group"), val => \$data->{2}[1], - list => [ qw(modp768 modp1024 modp1536 1 2 5) ], - help => N("define the group of Diffie-Hellman exponentiations. -If you do not require PFS then you can omit this directive. -Any proposal will be accepted if you do not specify one. -group is one of the following: modp768, modp1024, modp1536. -Or you can define 1, 2, or 5 as the DH group number.") }, - { label => N("Lifetime number"), val => \$data->{3}[2], type => 'entry', - help => N("define a lifetime of a certain time which will be pro- -posed in the phase 1 negotiations. Any proposal will be -accepted, and the attribute(s) will not be proposed to -the peer if you do not specify it(them). They can be -individually specified in each proposal. - -Examples: \n - lifetime time 1 min; # sec,min,hour - lifetime time 1 min; # sec,min,hour - lifetime time 30 sec; - lifetime time 30 sec; - lifetime time 60 sec; - lifetime time 12 hour; - -So, here, the lifetime numbers are 1, 1, 30, 30, 60 and 12. -") }, - { label => N("Lifetime unit"), val => \$data->{3}[3], - list => [ qw(sec min hour) ], - help => N("define a lifetime of a certain time which will be pro- -posed in the phase 1 negotiations. Any proposal will be -accepted, and the attribute(s) will not be proposed to -the peer if you do not specify it(them). They can be -individually specified in each proposal. - -Examples: \n - lifetime time 1 min; # sec,min,hour - lifetime time 1 min; # sec,min,hour - lifetime time 30 sec; - lifetime time 30 sec; - lifetime time 60 sec; - lifetime time 12 hour; - -So, here, the lifetime units are 'min', 'min', 'sec', 'sec', 'sec' and 'hour'. -") }, - { label => N("Encryption algorithm"), val => \$data->{4}[1], - list => [ qw(des 3des des_iv64 des_iv32 rc5 rc4 idea 3idea cast128 blowfish null_enc twofish rijndae) ] }, - { label => N("Authentication algorithm"), val => \$data->{5}[1], - list => [ qw(des 3des des_iv64 des_iv32 hmac_md5 hmac_sha1 non_auth) ] }, - { label => N("Compression algorithm"), val => \$data->{6}[1], - list => [ N_("deflate") ], format => \&translate, allow_empty_list => 1 } - -]) } - -sub ask_info2 { - my ($title, $text, $main_remote_section, $proposal_remote_section) = @_; - $in->ask_from($title, $text,, - [ { label => N("Remote"), val => \$main_remote_section->{1}[1], type => 'entry', - help => N("remote (address | anonymous) [[port]] { statements } -specifies the parameters for IKE phase 1 for each remote node. -The default port is 500. If anonymous is specified, the state- -ments apply to all peers which do not match any other remote -directive.\n -Examples: \n -remote anonymous -remote ::1 [8000]") }, - { label => N("Exchange mode"), val => \$main_remote_section->{2}[1], - list => [ qw(main,agressive agressive,main) ], - help => N("defines the exchange mode for phase 1 when racoon is the -initiator. Also it means the acceptable exchange mode -when racoon is responder. More than one mode can be -specified by separating them with a comma. All of the -modes are acceptable. The first exchange mode is what -racoon uses when it is the initiator.\n") }, - { label => N("Generate policy"), val => \$main_remote_section->{3}[1], - list => [ N_("off"), N_("on") ], format => \&translate, - help => N("This directive is for the responder. Therefore you -should set passive on in order that racoon(8) only -becomes a responder. If the responder does not have any -policy in SPD during phase 2 negotiation, and the direc- -tive is set on, then racoon(8) will choice the first pro- -posal in the SA payload from the initiator, and generate -policy entries from the proposal. It is useful to nego- -tiate with the client which is allocated IP address -dynamically. Note that inappropriate policy might be -installed into the responder's SPD by the initiator. So -that other communication might fail if such policies -installed due to some policy mismatches between the ini- -tiator and the responder. This directive is ignored in -the initiator case. The default value is off.") }, - { label => N("Passive"), val => \$main_remote_section->{4}[1], - list => [ N_("off"), N_("on") ], format => \&translate, - help => N("If you do not want to initiate the negotiation, set this -to on. The default value is off. It is useful for a -server.") }, - { label => N("Certificate type"), val => \$main_remote_section->{5}[1], - list => [ 'x509' ], allow_empty_list => 1 }, - { label => N("My certfile"), val => \$main_remote_section->{5}[2], type => 'entry', - help => N("Name of the certificate") }, - { label => N("My private key"), val => \$main_remote_section->{5}[3], type => 'entry', - help => N("Name of the private key") }, - { label => N("Peers certfile"), val => \$main_remote_section->{6}[1], type => 'entry', - help => N("Name of the peers certificate") }, - { label => N("Verify cert"), val => \$main_remote_section->{7}[1], - list => [ N_("off"), N_("on") ], format => \&translate, - help => N("If you do not want to verify the peer's certificate for -some reason, set this to off. The default is on.") }, - { label => N("My identifier"), val => \$main_remote_section->{8}[1], type => 'entry', - help => N("specifies the identifier sent to the remote host and the -type to use in the phase 1 negotiation. address, FQDN, -user_fqdn, keyid and asn1dn can be used as an idtype. -they are used like: - my_identifier address [address]; - the type is the IP address. This is the default - type if you do not specify an identifier to use. - my_identifier user_fqdn string; - the type is a USER_FQDN (user fully-qualified - domain name). - my_identifier FQDN string; - the type is a FQDN (fully-qualified domain name). - my_identifier keyid file; - the type is a KEY_ID. - my_identifier asn1dn [string]; - the type is an ASN.1 distinguished name. If - string is omitted, racoon(8) will get DN from - Subject field in the certificate.\n -Examples: \n -my_identifier user_fqdn \"myemail\@mydomain.com\"") }, - { label => N("Peers identifier"), val => \$main_remote_section->{9}[1], type => 'entry' }, - { label => N("Proposal"), val => \$proposal_remote_section->{1}[0], list => [ 'proposal' ], allow_empty_list => 1 }, - { label => N("Encryption algorithm"), val => \$proposal_remote_section->{2}[1], list => [ qw(des 3des blowfish cast128) ], - help => N("specify the encryption algorithm used for the -phase 1 negotiation. This directive must be defined. -algorithm is one of the following: - -DES, 3DES, blowfish, cast128 for oakley. - -For other transforms, this statement should not be used.") }, - { label => N("Hash algorithm"), val => \$proposal_remote_section->{3}[1], type => 'entry' }, - { label => N("Authentication method"), val => \$proposal_remote_section->{4}[1], type => 'entry' }, - { label => N("DH group"), val => \$proposal_remote_section->{5}[1], list => [ qw(modp768 modp1024 modp1536 1 2 5) ], }, - ]); -} - -sub ask_info3 { - my ($title, $text, $section) = @_; - $in->ask_from($title, $text,, - [ { label => N("Command"), val => \$section->{command}, list => [ 'spdadd' ], allow_empty_list => 1 }, - { label => N("Source IP range"), val => \$section->{src_range}, type => 'entry' }, - { label => N("Destination IP range"), val => \$section->{dst_range}, type => 'entry' }, - { label => N("Upper-layer protocol"), val => \$section->{upperspec}, list => [ N_("any") ], - format => \&translate, allow_empty_list => 1 }, - { label => N("Flag"), val => \$section->{flag}, list => [ '-P' ], allow_empty_list => 1 }, - { label => N("Direction"), val => \$section->{direction}, list => [ 'in', 'out' ] }, - { label => N("IPsec policy"), val => \$section->{ipsec}, list => [ N_("ipsec"), N_("discard"), N_("none") ], - format => \&translate }, - { label => N("Protocol"), val => \$section->{protocol}, list => [ 'esp', 'ah', 'ipcomp' ] }, - { label => N("Mode"), val => \$section->{mode}, list => [ N_("tunnel"), N_("transport"), N_("any") ], - format => \&translate }, - { label => N("Source/destination"), val => \$section->{src_dest}, type => 'entry' }, - { label => N("Level"), val => \$section->{level}, list => [ N_("require"), N_("default"), N_("use"), N_("unique") ], - format => \&translate }, - ]); -} +use network::drakvpn; +my $in = 'interactive'->vnew('su'); +network::drakvpn::create_connection($in); diff --git a/bin/drakvpn-old b/bin/drakvpn-old new file mode 100755 index 0000000..b658325 --- /dev/null +++ b/bin/drakvpn-old @@ -0,0 +1,847 @@ +#!/usr/bin/perl + +# +# author Florin Grad (florin@mandrakesoft.com) +# +# Copyright 2006 Mandriva +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2, as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + + +# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX) +BEGIN { unshift @::textdomains, 'drakx-net' } +use lib qw(/usr/lib/libDrakX); + +use standalone; #- warning, standalone must be loaded very first, for 'explanations' + +use common; +use detect_devices; +use interactive; +use network::network; +use log; +use c; +use network::netconnect; +use network::shorewall; +use network::ipsec; +use Data::Dumper; + +$::isInstall and die "Not supported during install.\n"; + + +local $_ = join '', @ARGV; + +$::Wizard_pix_up = "drakvpn.png"; +$ugtk2::wm_icon = "drakvpn"; + +my $direct = /-direct/; + +my $tunnels_file = "/etc/shorewall/tunnels"; +my $ipsec_conf = ""; +my $racoon_conf = "/etc/racoon/racoon.conf"; +my $ipsec_package = ""; + +my $in = interactive->vnew('su'); +my $shorewall = network::shorewall::read($in); +my @section_names; + + $ipsec_conf = "/etc/ipsec.conf"; +my $ipsec = network::ipsec::read_ipsec_conf($ipsec_conf); +my $racoon = network::ipsec::read_racoon_conf($racoon_conf); + +#print network::ipsec::display_ipsec_conf($ipsec_conf,$ipsec); + +$::Wizard_title = N("DrakVPN"); + +$in->isa('interactive::gtk') and $::isWizard = 1; + +my $wait_configuring; + +sub fatal_quit ($) { + log::l("[drakvpn] FATAL: $_[0]"); + undef $wait_configuring; + $in->ask_warn('', $_[0]); + quit_global($in, -1); +} + +begin: + +#- ********************************** +#- * 0th step: verify if we are already set up + +if ($shorewall && any { !/^\s*(?:#|\n)/ } cat_($tunnels_file)) { + $::Wizard_no_previous = 1; + + if (!$shorewall->{disabled}) { + my $r = $in->ask_from_list_(N("The VPN connection is enabled."), +N("The setup of a VPN connection has already been done. + +It's currently enabled. + +What would you like to do?"), + [ N_("disable"), N_("reconfigure"), N_("dismiss") ]) or quit_global($in, 0); + # FIXME: reconfigure is not handled + if ($r eq "disable") { + if (!$::testing) { + my $_wait_disabl = $in->wait_message('', N("Disabling VPN...")); + network::ipsec::stop_daemons(); + } + foreach ($ipsec_conf, $tunnels_file) { + if (-f $_) { rename($_, "$_.drakvpndisable") or die "Could not rename $_ to $_.drakvpndisable" } + } + network::ipsec::sys("/etc/init.d/shorewall restart >/dev/null"); + log::l("[drakvpn] Disabled"); + $::Wizard_finished = 1; + $in->ask_okcancel('', N("The VPN connection is now disabled.")); + quit_global($in, 0); + } + if ($r eq "dismiss") { + quit_global($in, 0); + } + } else { + my $r = $in->ask_from_list_(N("VPN connection currently disabled"), +N("The setup of a VPN connection has already been done. + +It's currently disabled. + +What would you like to do?"), + [ N_("enable"), N_("reconfigure"), N_("dismiss") ]); + # FIXME: reconfigure is not handled + if ($r eq "enable") { + foreach ($ipsec_conf, $tunnels_file) { + rename($_, "$_.old") if -f $_; + rename("$_.drakvpndisable", $_) or die "Could not find configuration. Please reconfigure."; + } + { + my $_wait_enabl = $in->wait_message('', N("Enabling VPN...")); + network::ipsec::start_daemons(); + } + log::l("[drakvpn] Enabled"); + } + $::Wizard_finished = 1; + $in->ask_okcancel('', N("The VPN connection is now enabled.")); + quit_global($in, 0); + if ($r eq "dismiss") { + quit_global($in, 0); + } + } + } + +#- ********************************** +#- * 1st step: detect/setup +step_ask_confirm: + +$::Wizard_no_previous = 1; + +$direct or $in->ask_okcancel(N("Simple VPN setup."), +N("You are about to configure your computer to use a VPN connection. + +With this feature, computers on your local private network and computers +on some other remote private networks, can share resources, through +their respective firewalls, over the Internet, in a secure manner. + +The communication over the Internet is encrypted. The local and remote +computers look as if they were on the same network. + +Make sure you have configured your Network/Internet access using +drakconnect before going any further."), 1) or goto begin; + +undef $::Wizard_no_previous; + + $ipsec_package = "ipsec-tools"; + +$direct or $in->ask_okcancel(N("Simple VPN setup."), +N("VPN connection. + +This program is based on the following projects: + - FreeSwan: \t\t\thttp://www.freeswan.org/ + - Super-FreeSwan: \t\thttp://www.freeswan.ca/ + - ipsec-tools: \t\t\thttp://ipsec-tools.sourceforge.net/ + - ipsec-howto: \t\thttp://www.ipsec-howto.org + - the docs and man pages coming with the %s package + +Please read AT LEAST the ipsec-howto docs +before going any further.",$ipsec_package)) or goto begin; + +step_detectsetup: + +#my @configured_devices = map { /ifcfg-(\S+)/ } glob('/etc/sysconfig/network-scripts/ifcfg*'); + +my %aliased_devices; +/^\s*alias\s+(eth[0-9])\s+(\S+)/ and $aliased_devices{$1} = $2 foreach cat_("/etc/modules.conf"); + +#- ********************************** +#- * 2nd step: configure + +#$wait_configuring = $in->wait_message(N("Configuring..."), +# N("Configuring scripts, installing software, starting servers...")); + + + +#- install and setup the RPM packages, if needed + +my %rpm2file; +log::l("[drakvpn] install the $ipsec_package and the shorewall rpm packages"); + %rpm2file = ($ipsec_package => '/sbin/setkey', + shorewall => '/sbin/shorewall'); + +#- first: try to install all in one step, if needed +if (!-e "/sbin/setkey") { + + my @needed_to_install = grep { !-e $rpm2file{$_} } keys %rpm2file; + @needed_to_install and $in->do_pkgs->install(@needed_to_install) if !$::testing; + #- second: try one by one if failure detected + if (!$::testing && any { !-e $rpm2file{$_} } keys %rpm2file) { + foreach (keys %rpm2file) { + -e $rpm2file{$_} or $in->do_pkgs->install($_); + -e $rpm2file{$_} or fatal_quit(N("Problems installing package %s", $_)); + } + } +} + +undef $wait_configuring; + +#- configure the $ipsec_conf file +#- Add, Remove config|conn entries + +step_configuration: + +my $c; + +my %messages = (ipsec => N("Security Policies"), racoon => N("IKE daemon racoon")); + + $in->ask_from(N("Configuration file"), +N("Configuration step! + +You need to define the Security Policies and then to +configure the automatic key exchange (IKE) daemon. +The KAME IKE daemon we're using is called 'racoon'. + +What would you like to configure?\n"), + [ { val => \$c, type => "list", list => [ keys %messages ], format => sub { $messages{$_[0]} } } ]) or goto step_detectsetup; + +#------------------------------------------------------------------- +#---------------------- configure ipsec_conf ----------------------- +#------------------------------------------------------------------- + +if ($c eq "ipsec" || $c eq "configure") { + +step_configure_ipsec_conf: + +@section_names = network::ipsec::get_section_names_ipsec_conf($ipsec) if $ipsec; + +my $choice = $section_names[0]; +my $d = $in->ask_from_list_(N("%s entries", $ipsec_conf), +N("The %s file contents +is divided into sections.\n +You can now:\n + - display, add, edit, or remove sections, then + - commit the changes + +What would you like to do?\n", $ipsec_conf), + [ N_("_:display here is a verb\nDisplay"), N_("Add"), N_("Edit"), N_("Remove"), N_("Commit") ]) or goto step_configuration; + +#my $existing_section = ""; + +#- display $ipsec_conf ------------------------- + +step_display_ipsec_conf: + +if ($d eq "display $ipsec_conf" || $d eq "_:display here is a verb\nDisplay") { + my $ipsec_exists = 0; + foreach my $key (keys %$ipsec) { + $ipsec_exists = 1 if $ipsec->{$key}; + } + if ($ipsec_exists) { + $in->ask_okcancel(N("_:display here is a verb\nDisplay configuration"), + network::ipsec::display_ipsec_conf($ipsec)); + goto step_configure_ipsec_conf; + } else { +$in->ask_okcancel(N("_:display here is a verb\nDisplay configuration"), +N("The %s file does not exist.\n +This must be a new configuration.\n +You'll have to go back and choose 'add'.\n", $ipsec_conf)); + goto step_configure_ipsec_conf; + } + +#- add --------------------- + +} elsif ($d eq "Add") { + +step_add_section: + +#- add ---- kernel 2.6 part ------------------------------- + + my $section = { command => 'spdadd', + src_range => 'src_network_address', + dst_range => 'dest_network_address', + upperspec => 'any', + flag => '-P', + direction => 'in or out', + ipsec => 'ipsec', + protocol => 'esp', + mode => 'tunnel', + src_dest => 'source-destination', + level => 'require' }; + +step_add_section_ipsec_conf_k26: + + ask_info3('', +N("Add a Security Policy.\n +You can now add a Security Policy.\n +Choose continue when you are done to write the data.\n"), $section) or goto step_configure_ipsec_conf; + +# $existing_section = network::ipsec::already_existing_section_ipsec_conf($section->{src_dest}, $ipsec); +# +# if ($existing_section eq "already existing") { +#$in->ask_okcancel(N("Exists!"), +#N("A section with this name already exists. +#The section names have to be unique.\n +#You'll have to go back and add another section +#or change the name of the section.\n")); +# goto step_add_section_ipsec_conf_k26; +#}; + + if (!$ipsec->{1}) { + put_in_hash($ipsec, { max(keys %$ipsec) + 1 => "#!/sbin/setkey -f" }); + put_in_hash($ipsec, { max(keys %$ipsec) + 1 => "flush;" }); + put_in_hash($ipsec, { max(keys %$ipsec) + 1 => "spdflush;" }); + } + + network::ipsec::add_section_ipsec_conf($section, $ipsec); + + @section_names = network::ipsec::get_section_names_ipsec_conf($ipsec); + + goto step_configure_ipsec_conf; + +#- edit --------------------- + +} elsif ($d eq "Edit") { + +step_edit_ipsec_conf: +$in->ask_from(N("Edit section"), +N("Your %s file has several sections or connections.\n +You can choose here below the one you want to edit +and then click on next.\n", $ipsec_conf), + [ { val => \$choice, list => \@section_names, label => N("Section names"), sort => 0, not_edit => 0 } ]) + or goto step_configure_ipsec_conf; + +my $number = network::ipsec::matched_section_key_number_ipsec_conf($choice,$ipsec); + + + ask_info3('', +N("Edit a Security Policy.\n +You can now edit a Security Policy.\n +Choose continue when you are done to write the data.\n"), $ipsec->{$number}) or goto step_configure_ipsec_conf; + +goto step_configure_ipsec_conf; + +#- remove --------------------- + +} elsif ($d eq "Remove") { +$in->ask_from(N("Remove section"), +N("Your %s file has several sections or connections.\n +You can choose here below the one you want to remove +and then click on next.\n", $ipsec_conf), + [ { val => \$choice, list => \@section_names, label => N("Section names"), sort => 0, not_edit => 0 } ]); + + network::ipsec::remove_section_ipsec_conf($choice,$ipsec); + + @section_names = network::ipsec::get_section_names_ipsec_conf($ipsec) if $ipsec; + + goto step_configure_ipsec_conf; + +#- continue and write --------------------- + +} elsif ($d eq "Commit") { + log::l("[drakvpn] Modify the $ipsec_conf file"); + network::ipsec::write_ipsec_conf($ipsec_conf, $ipsec); + } +#------------------------------------------------------------------- +#---------------------- configure racoon_conf ----------------------- +#------------------------------------------------------------------- + +} elsif ($c eq "racoon") { + +step_configure_racoon_conf: + +@section_names = network::ipsec::get_section_names_racoon_conf($racoon) if $racoon; + +my $choice = $section_names[0]; +my $d = $in->ask_from_list_(N("%s entries", $racoon_conf), +N("The racoon.conf file configuration.\n +The contents of this file is divided into sections. +You can now: + - display \t\t (display the file contents) + - add \t\t (add one section) + - edit \t\t\t (modify parameters of an existing section) + - remove \t\t (remove an existing section) + - commit \t\t (writes the changes to the real file)"), + [ N_("_:display here is a verb\nDisplay"), N_("Add"), N_("Edit"), N_("Remove"), N_("Commit") ]) or goto step_configuration; + + +#- display $racoon_conf ------------------------- + +step_display_racoon_conf: + +if ($d eq "_:display here is a verb\nDisplay") { + + my $racoon_exists = 0; + foreach my $key (keys %$racoon) { + $racoon_exists = 1 if $racoon->{$key}; + } + + if ($racoon_exists) { + $in->ask_okcancel(N("_:display here is a verb\nDisplay configuration"), + network::ipsec::display_racoon_conf($racoon)); + goto step_configure_racoon_conf; + } else { +$in->ask_okcancel(N("_:display here is a verb\nDisplay configuration"), +N("The %s file does not exist\n +This must be a new configuration.\n +You'll have to go back and choose configure.\n", $racoon_conf)); + goto step_configure_racoon_conf; + } + +#- add $racoon_conf ------------------------------ + +} elsif ($d eq "Add") { + +step_add_section_racoon: + +#my $existing_section = ""; + +my $e = $in->ask_from_list_(N("racoon.conf entries"), +N("The 'add' sections step.\n +Here below is the racoon.conf file skeleton: +\t'path' +\t'remote' +\t'sainfo' \n +Choose the section you would like to add.\n"), + [ N_("path"), N_("remote"), N_("sainfo"), N_("dismiss") ]) or goto step_configure_racoon_conf; +if ($e eq "path") { + + my $path_section = { + 1 => [ 'path', 'path_type', '"/etc/racoon/certs"' ], + }; + + $in->ask_from('', +N("The 'add path' section step.\n +The path sections have to be on top of your racoon.conf file.\n +Put your mouse over the certificate entry to obtain online help."), + [ { label => N("path type"), + val => \$path_section->{1}[1], + list => [ 'certificate', 'pre_shared_key', 'include' ], + help => +N("path include path: specifies a path to include +a file. See File Inclusion. + Example: path include '/etc/racoon' + +path pre_shared_key file: specifies a file containing +pre-shared key(s) for various ID(s). See Pre-shared key File. + Example: path pre_shared_key '/etc/racoon/psk.txt' ; + +path certificate path: racoon(8) will search this directory +if a certificate or certificate request is received. + Example: path certificate '/etc/cert' ; + +File Inclusion: include file +other configuration files can be included. + Example: include \"remote.conf\" ; + +Pre-shared key File: Pre-shared key file defines a pair +of the identifier and the shared secret key which are used at +Pre-shared key authentication method in phase 1."), +}, + { label => N("real file"), val => \$path_section->{1}[2], type => 'entry' }, + ] +) or goto step_configure_racoon_conf; + +network::ipsec::add_section_racoon_conf($path_section, $racoon); +} elsif ($e eq "remote") { + my $main_remote_section = { 1 => [ 'remote', 'address' ], + 2 => [ 'exchange_mode', 'aggressive,main' ], + 3 => [ 'generate_policy', 'on' ], + 4 => [ 'passive', 'on' ], + 5 => [ 'certificate_type', 'x509', '"my_certificate.pem"', '"my_private_key.pem"' ], + 6 => [ 'peers_certfile', '"remote.public"' ], + 7 => [ 'verify_cert', 'on' ], + 8 => [ 'my_identifier', 'asn1dn' ], + 9 => [ 'peers_identifier', 'asn1dn' ] + }; + my $proposal_remote_section = { 1 => [ 'proposal' ], + 2 => [ 'encryption_algorithm', '3des' ], + 3 => [ 'hash_algorithm', 'md5' ], + 4 => [ 'authentication_method', 'rsasig' ], + 5 => [ 'dh_group', 'modp1024' ] + }; + ask_info2('', +N("Make sure you already have the path sections +on the top of your racoon.conf file. + +You can now choose the remote settings. +Choose continue or previous when you are done.\n"), $main_remote_section, $proposal_remote_section) or goto step_configure_racoon_conf; + +network::ipsec::add_section_racoon_conf($main_remote_section, $racoon); +network::ipsec::add_section_racoon_conf($proposal_remote_section, $racoon); +} elsif ($e eq "sainfo") { + my $sainfo_section = { 1 => [ 'sainfo', 'address', '192.168.100.2', 'any', 'address', '10.0.0.2', 'any' ], + 2 => [ 'pfs_group', '1' ], + 3 => [ 'lifetime', 'time', '30', 'sec' ], + 4 => [ 'encryption_algorithm', '3des' ], + 5 => [ 'authentication_algorithm', 'hmac_sha1' ], + 6 => [ 'compression_algorithm', 'deflate' ], + }; + ask_info('', +N("Make sure you already have the path sections +on the top of your %s file. + +You can now choose the sainfo settings. +Choose continue or previous when you are done.\n", $racoon_conf), $sainfo_section) or goto step_configure_racoon_conf; + +network::ipsec::add_section_racoon_conf($sainfo_section, $racoon); +} + +@section_names = network::ipsec::get_section_names_racoon_conf($racoon) if $racoon; + +goto step_configure_racoon_conf; + +#- edit $racoon_conf ----------------------------- + +} elsif ($d eq "Edit") { +$in->ask_from(N("Edit section"), +N("Your %s file has several sections or connections. + +You can choose here in the list below the one you want +to edit and then click on next.\n", $racoon_conf), + [ { val => \$choice, list => \@section_names, label => N("Section names"), sort => 0, not_edit => 0 } ]) + or goto step_configure_racoon_conf; + +my $number = network::ipsec::matched_section_key_number_racoon_conf($choice,$racoon); + +if ($choice =~ /^remote/) { + ask_info2('', +N("Your %s file has several sections.\n + +You can now edit the remote section entries. + +Choose continue when you are done to write the data.\n", $racoon_conf), $racoon->{$number}, $racoon->{$number+2}) + or goto step_configure_racoon_conf; + +} elsif ($choice =~ /^sainfo/) { + ask_info('', +N("Your %s file has several sections. + +You can now edit the sainfo section entries. + +Choose continue when you are done to write the data.", $racoon_conf), $racoon->{$number}) or goto step_configure_racoon_conf; + +} elsif ($choice =~ /^path/) { + $in->ask_from('', +N("This section has to be on top of your +%s file.\n +Make sure all other sections follow these path +sections.\n +You can now edit the path entries. + +Choose continue or previous when you are done.\n", $racoon_conf), + [ { label => N("path_type"), val => \$racoon->{$number}{1}[1], list => [ 'certificate', 'pre_shared_key', 'include' ] }, + { label => N("real file"), val => \$racoon->{$number}{1}[2], type => 'entry' }, + ] +) or goto step_configure_racoon_conf; +} + +goto step_configure_racoon_conf; + +#- remove $racoon_conf --------------------------- + +} elsif ($d eq "Remove") { +$in->ask_from(N("Remove section"), +N("Your %s file has several sections or connections.\n +You can choose here below the one you want to remove +and then click on next.\n", $racoon_conf), + [ { val => \$choice, list => \@section_names, label => N("Section names"), sort => 0, not_edit => 0 } ]); + +my $number = network::ipsec::matched_section_key_number_racoon_conf($choice,$racoon); +network::ipsec::remove_section_racoon_conf($choice,$racoon,$number); + @section_names = network::ipsec::get_section_names_racoon_conf($racoon) if $racoon; + + goto step_configure_racoon_conf; + +#- write $racoon_conf and continue --------------- +} elsif ($d eq "Commit") { + log::l("[drakvpn] Modify the $racoon_conf file"); + network::ipsec::write_racoon_conf($racoon_conf, $racoon); +} +} + +#- start the daemons +network::ipsec::start_daemons(); + +#- bye-bye message + +undef $wait_configuring; + +$::Wizard_no_previous = 1; +$::Wizard_finished = 1; + +$in->ask_okcancel(N("Congratulations!"), +N("Everything has been configured.\n +You may now share resources through the Internet, +in a secure way, using a VPN connection. + +You should make sure that the tunnels shorewall +section is configured.")); + +log::l("[drakvpn] Installation complete, exiting"); +quit_global($in, 0); + +sub quit_global { + my ($in, $exitcode) = @_; + $in->exit($exitcode); + goto begin; +} + + +sub ask_info { + my ($title, $text, $data) = @_; + $in->ask_from($title, $text, + [ { label => N("Sainfo source address"), val => \$data->{1}[2], type => 'entry', + help => N("sainfo (source_id destination_id | anonymous) { statements } +defines the parameters of the IKE phase 2 +(IPsec-SA establishment). + +source_id and destination_id are constructed like: + + address address [/ prefix] [[port]] ul_proto + +Examples: \n +sainfo anonymous (accepts connections from anywhere) + leave blank this entry if you want anonymous + +sainfo address 203.178.141.209 any address 203.178.141.218 any + 203.178.141.209 is the source address + +sainfo address 172.16.1.0/24 any address 172.16.2.0/24 any + 172.16.1.0/24 is the source address") }, + { label => N("Sainfo source protocol"), val => \$data->{1}[3], type => 'entry', + help => N("sainfo (source_id destination_id | anonymous) { statements } +defines the parameters of the IKE phase 2 +(IPsec-SA establishment). + +source_id and destination_id are constructed like: + + address address [/ prefix] [[port]] ul_proto + +Examples: \n +sainfo anonymous (accepts connections from anywhere) + leave blank this entry if you want anonymous + +sainfo address 203.178.141.209 any address 203.178.141.218 any + the first 'any' allows any protocol for the source") }, + { label => N("Sainfo destination address"), val => \$data->{1}[5], type => 'entry', + help => N("sainfo (source_id destination_id | anonymous) { statements } +defines the parameters of the IKE phase 2 +(IPsec-SA establishment). + +source_id and destination_id are constructed like: + + address address [/ prefix] [[port]] ul_proto + +Examples: \n +sainfo anonymous (accepts connections from anywhere) + leave blank this entry if you want anonymous + +sainfo address 203.178.141.209 any address 203.178.141.218 any + 203.178.141.218 is the destination address + +sainfo address 172.16.1.0/24 any address 172.16.2.0/24 any + 172.16.2.0/24 is the destination address") }, + { label => N("Sainfo destination protocol"), val => \$data->{1}[6], type => 'entry', + help => N("sainfo (source_id destination_id | anonymous) { statements } +defines the parameters of the IKE phase 2 +(IPsec-SA establishment). + +source_id and destination_id are constructed like: + + address address [/ prefix] [[port]] ul_proto + +Examples: \n +sainfo anonymous (accepts connections from anywhere) + leave blank this entry if you want anonymous + +sainfo address 203.178.141.209 any address 203.178.141.218 any + the last 'any' allows any protocol for the destination") }, + { label => N("PFS group"), val => \$data->{2}[1], + list => [ qw(modp768 modp1024 modp1536 1 2 5) ], + help => N("define the group of Diffie-Hellman exponentiations. +If you do not require PFS then you can omit this directive. +Any proposal will be accepted if you do not specify one. +group is one of the following: modp768, modp1024, modp1536. +Or you can define 1, 2, or 5 as the DH group number.") }, + { label => N("Lifetime number"), val => \$data->{3}[2], type => 'entry', + help => N("define a lifetime of a certain time which will be pro- +posed in the phase 1 negotiations. Any proposal will be +accepted, and the attribute(s) will not be proposed to +the peer if you do not specify it(them). They can be +individually specified in each proposal. + +Examples: \n + lifetime time 1 min; # sec,min,hour + lifetime time 1 min; # sec,min,hour + lifetime time 30 sec; + lifetime time 30 sec; + lifetime time 60 sec; + lifetime time 12 hour; + +So, here, the lifetime numbers are 1, 1, 30, 30, 60 and 12. +") }, + { label => N("Lifetime unit"), val => \$data->{3}[3], + list => [ qw(sec min hour) ], + help => N("define a lifetime of a certain time which will be pro- +posed in the phase 1 negotiations. Any proposal will be +accepted, and the attribute(s) will not be proposed to +the peer if you do not specify it(them). They can be +individually specified in each proposal. + +Examples: \n + lifetime time 1 min; # sec,min,hour + lifetime time 1 min; # sec,min,hour + lifetime time 30 sec; + lifetime time 30 sec; + lifetime time 60 sec; + lifetime time 12 hour; + +So, here, the lifetime units are 'min', 'min', 'sec', 'sec', 'sec' and 'hour'. +") }, + { label => N("Encryption algorithm"), val => \$data->{4}[1], + list => [ qw(des 3des des_iv64 des_iv32 rc5 rc4 idea 3idea cast128 blowfish null_enc twofish rijndae) ] }, + { label => N("Authentication algorithm"), val => \$data->{5}[1], + list => [ qw(des 3des des_iv64 des_iv32 hmac_md5 hmac_sha1 non_auth) ] }, + { label => N("Compression algorithm"), val => \$data->{6}[1], + list => [ N_("deflate") ], format => \&translate, allow_empty_list => 1 } + +]) } + +sub ask_info2 { + my ($title, $text, $main_remote_section, $proposal_remote_section) = @_; + $in->ask_from($title, $text,, + [ { label => N("Remote"), val => \$main_remote_section->{1}[1], type => 'entry', + help => N("remote (address | anonymous) [[port]] { statements } +specifies the parameters for IKE phase 1 for each remote node. +The default port is 500. If anonymous is specified, the state- +ments apply to all peers which do not match any other remote +directive.\n +Examples: \n +remote anonymous +remote ::1 [8000]") }, + { label => N("Exchange mode"), val => \$main_remote_section->{2}[1], + list => [ qw(main,agressive agressive,main) ], + help => N("defines the exchange mode for phase 1 when racoon is the +initiator. Also it means the acceptable exchange mode +when racoon is responder. More than one mode can be +specified by separating them with a comma. All of the +modes are acceptable. The first exchange mode is what +racoon uses when it is the initiator.\n") }, + { label => N("Generate policy"), val => \$main_remote_section->{3}[1], + list => [ N_("off"), N_("on") ], format => \&translate, + help => N("This directive is for the responder. Therefore you +should set passive on in order that racoon(8) only +becomes a responder. If the responder does not have any +policy in SPD during phase 2 negotiation, and the direc- +tive is set on, then racoon(8) will choose the first pro- +posal in the SA payload from the initiator, and generate +policy entries from the proposal. It is useful to nego- +tiate with the client which is allocated IP address +dynamically. Note that inappropriate policy might be +installed into the responder's SPD by the initiator. So +that other communication might fail if such policies +installed due to some policy mismatches between the ini- +tiator and the responder. This directive is ignored in +the initiator case. The default value is off.") }, + { label => N("Passive"), val => \$main_remote_section->{4}[1], + list => [ N_("off"), N_("on") ], format => \&translate, + help => N("If you do not want to initiate the negotiation, set this +to on. The default value is off. It is useful for a +server.") }, + { label => N("Certificate type"), val => \$main_remote_section->{5}[1], + list => [ 'x509' ], allow_empty_list => 1 }, + { label => N("My certfile"), val => \$main_remote_section->{5}[2], type => 'entry', + help => N("Name of the certificate") }, + { label => N("My private key"), val => \$main_remote_section->{5}[3], type => 'entry', + help => N("Name of the private key") }, + { label => N("Peers certfile"), val => \$main_remote_section->{6}[1], type => 'entry', + help => N("Name of the peers certificate") }, + { label => N("Verify cert"), val => \$main_remote_section->{7}[1], + list => [ N_("off"), N_("on") ], format => \&translate, + help => N("If you do not want to verify the peer's certificate for +some reason, set this to off. The default is on.") }, + { label => N("My identifier"), val => \$main_remote_section->{8}[1], type => 'entry', + help => N("specifies the identifier sent to the remote host and the +type to use in the phase 1 negotiation. address, FQDN, +user_fqdn, keyid and asn1dn can be used as an idtype. +they are used like: + my_identifier address [address]; + the type is the IP address. This is the default + type if you do not specify an identifier to use. + my_identifier user_fqdn string; + the type is a USER_FQDN (user fully-qualified + domain name). + my_identifier FQDN string; + the type is a FQDN (fully-qualified domain name). + my_identifier keyid file; + the type is a KEY_ID. + my_identifier asn1dn [string]; + the type is an ASN.1 distinguished name. If + string is omitted, racoon(8) will get DN from + Subject field in the certificate.\n +Examples: \n +my_identifier user_fqdn \"myemail\@mydomain.com\"") }, + { label => N("Peers identifier"), val => \$main_remote_section->{9}[1], type => 'entry' }, + { label => N("Proposal"), val => \$proposal_remote_section->{1}[0], list => [ 'proposal' ], allow_empty_list => 1 }, + { label => N("Encryption algorithm"), val => \$proposal_remote_section->{2}[1], list => [ qw(des 3des blowfish cast128) ], + help => N("specify the encryption algorithm used for the +phase 1 negotiation. This directive must be defined. +algorithm is one of the following: + +DES, 3DES, blowfish, cast128 for oakley. + +For other transforms, this statement should not be used.") }, + { label => N("Hash algorithm"), val => \$proposal_remote_section->{3}[1], type => 'entry' }, + { label => N("Authentication method"), val => \$proposal_remote_section->{4}[1], type => 'entry' }, + { label => N("DH group"), val => \$proposal_remote_section->{5}[1], list => [ qw(modp768 modp1024 modp1536 1 2 5) ], }, + ]); +} + +sub ask_info3 { + my ($title, $text, $section) = @_; + $in->ask_from($title, $text,, + [ { label => N("Command"), val => \$section->{command}, list => [ 'spdadd' ], allow_empty_list => 1 }, + { label => N("Source IP range"), val => \$section->{src_range}, type => 'entry' }, + { label => N("Destination IP range"), val => \$section->{dst_range}, type => 'entry' }, + { label => N("Upper-layer protocol"), val => \$section->{upperspec}, list => [ N_("any") ], + format => \&translate, allow_empty_list => 1 }, + { label => N("Flag"), val => \$section->{flag}, list => [ '-P' ], allow_empty_list => 1 }, + { label => N("Direction"), val => \$section->{direction}, list => [ 'in', 'out' ] }, + { label => N("IPsec policy"), val => \$section->{ipsec}, list => [ N_("ipsec"), N_("discard"), N_("none") ], + format => \&translate }, + { label => N("Protocol"), val => \$section->{protocol}, list => [ 'esp', 'ah', 'ipcomp' ] }, + { label => N("Mode"), val => \$section->{mode}, list => [ N_("tunnel"), N_("transport"), N_("any") ], + format => \&translate }, + { label => N("Source/destination"), val => \$section->{src_dest}, type => 'entry' }, + { label => N("Level"), val => \$section->{level}, list => [ N_("require"), N_("default"), N_("use"), N_("unique") ], + format => \&translate }, + ]); +} + diff --git a/bin/net_applet b/bin/net_applet index a0c9efe..d4eb999 100644 --- a/bin/net_applet +++ b/bin/net_applet @@ -2,20 +2,26 @@ use strict; use lib qw(/usr/lib/libDrakX); +# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX) +BEGIN { unshift @::textdomains, 'drakx-net' } use c; use common; use standalone; use network::network; use network::tools; +use network::connection; +use network::connection::ethernet; +use network::vpn; use run_program; -use mygtk2 qw(gtknew); +use mygtk2 qw(gtknew gtkset); use dbus_object; use network::ifw; use network::monitor; +use network::signal_strength; use detect_devices; +use modules; use Gtk2::TrayIcon; -use Gtk2::NotificationBubble; use ugtk2 qw(:create :helpers :wrappers :dialogs); @@ -24,33 +30,45 @@ shouldStart() or die "$onstartupfile should be set to TRUE or use net_applet --f #- Allow multiple instances, but only one per user: is_running('net_applet') and die "net_applet already running\n"; -my ($eventbox, $img, $bubble); -my ($current_state, $current_interface, $menu, $wireless_device, $wireless_menu, $timeout, $update_timeout); +my ($eventbox, $img); +my ($current_state, $current_interface, $current_description, $simple_menu, $menu, $wireless_device, $timeout, $update_timeout); add_icon_path("/usr/share/libDrakX/pixmaps/"); my $net = {}; +my $modules_conf = modules::any_conf->read; my $watched_interface; my %pixbufs = ( - firewall => gtkcreate_pixbuf('/usr/lib/libDrakX/icons/drakfirewall.png'), - firewall_icon => gtkcreate_pixbuf('/usr/lib/libDrakX/icons/drakfirewall.png')->scale_simple(24, 24, 'hyper'), - state => { map { $_ => gtkcreate_pixbuf($_) } qw(connected disconnected) }, + firewall => gtknew('Pixbuf', file => 'drakfirewall.png'), + firewall_icon => gtknew('Pixbuf', file => 'drakfirewall.png')->scale_simple(24, 24, 'hyper'), + state => { map { $_ => gtknew('Pixbuf', file => $_) } qw(connected disconnected) }, link_level => { map { - $_ => gtkcreate_pixbuf('wifi-' . sprintf('%03d', $_) . '.png')->scale_simple(24, 24, 'hyper'); + $_ => gtknew('Pixbuf', file => 'wifi-' . sprintf('%03d', $_) . '.png')->scale_simple(24, 24, 'hyper'); } qw(20 40 60 80 100) }, - keyring => gtkcreate_pixbuf("/usr/share/pixmaps/keyring-small.png")->scale_simple(24, 24, 'hyper'), #- provided by usermode, required by drakxtools + encryption => { map { + $_ => gtknew('Pixbuf', file => "encryption-$_-24.png"); + } qw(open weak strong) }, ); my %wireless_networks; -my %tooltips = - ( - connected => N_("Network is up on interface %s"), - disconnected => - #-PO: keep the "Configure Network" substring synced with the "Configure Network" message below - N_("Network is down on interface %s. Click on \"Configure Network\""), - notconfigured => 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, ...)")), - ); + +sub get_state_message { + my ($o_interface) = @_; + my $interface = $o_interface || $current_interface; + my $network = get_current_network(); + formatAlaTeX( + $current_state eq 'connected' ? + N("Network is up on interface %s.", $interface) . + "\n\n" . N("IP address: %s", network::tools::get_interface_ip_address($net, $interface)) . + "\n\n" . N("Gateway: %s", [ network::tools::get_interface_status($interface) ]->[1]) . + ($network && "\n\n" . N("Connected to %s (link level: %d %%)", $network->{name}, $network->{signal_strength})) + : $current_state eq 'disconnected' ? + N("Network is down on interface %s.", $interface) + : + 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, ...)")) + ); +} my %actions = ( 'upNetwork' => { name => sub { N("Connect %s", $_[0]) }, launch => sub { network::tools::start_interface($_[0], 1) } }, @@ -58,7 +76,12 @@ my %actions = ( 'monitorNetwork' => { name => N("Monitor Network"), launch => \&run_net_monitor }, 'monitorIFW' => { name => N("Interactive Firewall"), launch => \&run_drakids }, 'wireless' => { name => N("Manage wireless networks"), launch => sub { run_drakroam() } }, - 'confNetwork' => { name => N("Configure Network"), launch => sub { system("/usr/sbin/drakconnect --skip-wizard &") } }, + 'drakvpn' => { + name => N("Manage VPN connections"), launch => sub { + run_program::raw({ detach => 1 }, '/usr/sbin/drakvpn'); + }, + }, + 'confNetwork' => { name => N("Configure Network"), launch => sub { system("/usr/sbin/drakconnect &") } }, 'chooseInterface' => { name => N("Watched interface"), choices => sub { N("Auto-detect"), sort keys %{$net->{ifcfg}} }, @@ -76,6 +99,12 @@ my %actions = ( my ($is_up, $_gw) = network::tools::get_interface_status($_[0]); $is_up; }, + get_icon => sub { + my $ifcfg = $net->{ifcfg}{$_[0]}; + require network::connection; + my $type = $ifcfg && network::connection->find_ifcfg_type($ifcfg); + $type && $type->get_type_icon; + }, launch => sub { my ($is_up, $_gw) = network::tools::get_interface_status($_[0]); if ($is_up) { @@ -93,9 +122,18 @@ my %actions = ( launch => sub { require run_program; $net->{PROFILE} = $_[0]; - run_program::raw({ detach => 1 }, network::tools::wrap_command_for_root('/sbin/set-netprofile', $net->{PROFILE})); + run_program::raw({ detach => 1 }, common::wrap_command_for_root('/sbin/set-netprofile', $net->{PROFILE})); } }, + 'chooseVPN' => { + name => N("VPN connection"), + header => "drakvpn", + choices => sub { map { $_->get_configured_connections } network::vpn::list_types }, + allow_single_choice => 1, + format_choice => \&network::vpn::get_label, + choice_selected => sub { $_[0]->is_started }, + launch => sub { require interactive; $_[0]->is_started ? $_[0]->stop : $_[0]->start(interactive->vnew) }, + }, 'help' => { name => N("Get Online Help"), launch => sub { system("drakhelp --id internet-connection &") } }, 'quit' => { name => N("Quit"), launch => \&mainQuit }, ); @@ -107,7 +145,7 @@ gtkadd(my $icon = Gtk2::TrayIcon->new("Net_Applet"), ); $icon->show_all; -my ($dbus, $monitor, $ifw, $interactive_cb, @attacks_queue, $ifw_alert); +my ($dbus, $monitor, $ifw, $interactive_cb, $ifw_alert); eval { $dbus = dbus_object::system_bus() }; eval { $monitor = network::monitor->new($dbus) } if $dbus; eval { @@ -115,7 +153,9 @@ eval { my ($_con, $msg) = @_; my $member = $msg->get_member; if ($member eq 'Attack') { - handle_attack($msg->get_args_list); + handle_ifw_message($msg->get_args_list); + } elsif ($member eq 'Listen') { + handle_ifw_listen($msg->get_args_list); } elsif ($member eq 'Init') { $ifw->attach_object; checkNetworkForce(); @@ -125,27 +165,24 @@ eval { }); } if $dbus; -$bubble = Gtk2::NotificationBubble->new; -$bubble->attach($icon); -$bubble->signal_connect(timeout => sub { - set_verdict($attacks_queue[0], \&apply_verdict_ignore); -}); -$bubble->signal_connect(clicked => sub { - $bubble->hide; - eval { $ifw->send_alert_ack }; - $ifw_alert = 0; - update_tray_icon(); - ask_attack_verdict($attacks_queue[0]); -}); +my $bubble_queue = Gtk2::NotificationBubble::Queue->new; +$bubble_queue->{bubble}->attach($icon); $eventbox->signal_connect(button_press_event => sub { - $_[1]->button == 1 and ($ifw_alert ? run_drakids() : run_net_monitor()); - $_[1]->button == 3 && $menu and $menu->popup(undef, undef, undef, undef, $_[1]->button, $_[1]->time); + if ($_[1]->button == 1) { + if ($ifw_alert) { + run_drakids(); + } elsif ($simple_menu) { + $simple_menu->popup(undef, undef, undef, undef, $_[1]->button, $_[1]->time); + } + } elsif ($_[1]->button == 3 && $menu) { + $menu->popup(undef, undef, undef, undef, $_[1]->button, $_[1]->time); + } }); checkNetworkForce(); cronNetwork(); -get_unprocessed_attacks(); +get_unprocessed_ifw_messages(); $SIG{HUP} = sub { print "received SIGHUP, reloading network configuration\n"; @@ -160,7 +197,7 @@ sub is_running { my ($name) = @_; any { my ($ppid, $pid, $n) = /^\s*(\d+)\s+(\d+)\s+(.*)/; - $pid != $$ && $n eq $name; + $ppid != 1 && $pid != $$ && $n eq $name; } `ps -o '%P %p %c' -u $ENV{USER}`; } sub shouldStart() { @@ -186,44 +223,57 @@ sub run_drakids() { } } sub generate_wireless_menuitem { - my ($wnet, $ap) = @_; - $wnet->{menuitem} = Gtk2::CheckMenuItem->new; - $wnet->{menuitem}->set_draw_as_radio(1); - $wnet->{menuitem}->add(gtkpack_(gtkshow(Gtk2::HBox->new), - 1, gtkset_alignment($wnet->{ssid_label} = Gtk2::Label->new, 0, 0), - 0, $wnet->{keyring_image} = Gtk2::Image->new_from_pixbuf($pixbufs{keyring}), - 0, $wnet->{level_image} = Gtk2::Image->new)); - $wnet->{activate} = $wnet->{menuitem}->signal_connect('activate' => sub { + my ($wnet) = @_; + my $menuitem = {}; + $menuitem->{widget} = Gtk2::CheckMenuItem->new; + $menuitem->{widget}->set_draw_as_radio(1); + $menuitem->{widget}->add(gtkpack_(gtkshow(gtknew('HBox')), + 1, gtkset_alignment($menuitem->{label} = gtknew('Label'), 0, 0.5), + 0, $menuitem->{strength} = Gtk2::Image->new, + 0, $menuitem->{security} = Gtk2::Image->new, + )); + $menuitem->{activate} = $menuitem->{widget}->signal_connect('activate' => sub { if (exists $wnet->{id}) { eval { $monitor->select_network($wnet->{id}) }; $@ and err_dialog(N("Interactive Firewall"), N("Unable to contact daemon")); } else { - run_drakroam($ap); + run_drakroam($wnet->{ap}); } checkNetworkForce(); }); - undef $current_state; #- force menu redraw + update_wireless_item($menuitem, $wnet); + push @{$wnet->{menuitems}}, $menuitem; + return $menuitem->{widget}; } sub update_wireless_item { - my ($wnet, $ap_address) = @_; - $wnet->{ssid_label}->set_text($wnet->{essid} || "[$ap_address]"); - $wnet->{keyring_image}->visible(to_bool($wnet->{flags})); - $wnet->{level_image}->set_from_pixbuf($pixbufs{link_level}{$wnet->{approx_level}}); - - $wnet->{menuitem}->signal_handler_block($wnet->{activate}); - $wnet->{menuitem}->set_active($wnet->{current}); - $wnet->{menuitem}->signal_handler_unblock($wnet->{activate}); + my ($menuitem, $wnet) = @_; + $menuitem->{label}->set_text($wnet->{name}); + $menuitem->{security}->set_from_pixbuf($pixbufs{encryption}{$wnet->{flags} =~ /WPA/i ? 'strong' : $wnet->{flags} =~ /WEP/i ? 'weak' : 'open'}); + $menuitem->{strength}->set_from_pixbuf(network::signal_strength::get_strength_icon($wnet)); + + $menuitem->{widget}->signal_handler_block($menuitem->{activate}); + $menuitem->{widget}->set_active($wnet->{current}); + $menuitem->{widget}->signal_handler_unblock($menuitem->{activate}); } sub checkWireless() { $wireless_device or return; - my ($networks) = network::monitor::list_wireless($monitor, $wireless_device); + my ($networks) = network::monitor::list_wireless($monitor); + my $force_applet_update; foreach (keys %$networks) { - my $wnet = $wireless_networks{$_} ||= {}; - put_in_hash($wnet, $networks->{$_}); - exists $wnet->{menuitem} or generate_wireless_menuitem($wnet, $_); - update_wireless_item($wnet, $_); + exists $wireless_networks{$_} or $force_applet_update = 1; + put_in_hash($wireless_networks{$_} ||= {}, $networks->{$_}); + } + if ($force_applet_update) { + undef $current_state; + } else { + foreach my $wnet (values %wireless_networks) { + my $is_valuable = exists $networks->{$wnet->{ap}}; + foreach (@{$wnet->{menuitems}}) { + update_wireless_item($_, $wnet) if $is_valuable; + $_->{widget}->visible($is_valuable); + } + } } - $wireless_networks{$_}{menuitem}->visible(exists $networks->{$_}) foreach keys %wireless_networks; } sub checkNetwork() { my ($gw_intf, $_is_up, $gw_address) = $watched_interface ? @@ -249,85 +299,172 @@ sub cronNetwork() { } sub go2State { my ($state_type, $interface) = @_; - if ($current_state ne $state_type || $current_interface ne $interface) { - $current_state = $state_type; - $current_interface = $interface; - $wireless_device = detect_devices::get_wireless_interface(); - if ($menu) { - if (my $m = $wireless_menu && $wireless_menu->get_submenu) { - $_->{menuitem}->get_parent and $m->remove($_->{menuitem}) foreach values %wireless_networks; - } - $menu->destroy; + my $need_update; + my ($old_interface, $old_description); + if ($current_interface ne $interface) { + my $card = find { $_->[0] eq $interface } network::connection::ethernet::get_eth_cards($modules_conf); + if ($state_type eq 'disconnected') { + $old_interface = $current_interface; + $old_description = $current_description; } - $menu = generate_menu($interface); + $current_description = $card && $card->[2]; + $current_interface = $interface; + $need_update = 1; + } + if ($current_state ne $state_type) { + my $show = defined $current_state; # don't show bubble at applet startup + $current_state = $state_type; + $bubble_queue->add({ + title => $old_description || $current_description || N("Network connection"), + pixbuf => get_state_pixbuf(), + message => get_state_message($old_interface || $current_interface), + }) if $show; + $need_update = 1; + } + + update_applet() if $need_update; +} + +sub get_current_network() { + detect_devices::is_wireless_interface($current_interface) && find { $_->{current} } values %wireless_networks; +} + +sub get_state_pixbuf() { + my $pixbuf; + if ($current_state eq 'connected') { + my $wnet = get_current_network(); + $pixbuf = $wnet ? + network::signal_strength::get_strength_icon($wnet) : + $pixbufs{state}{connected}; + } else { + $pixbuf = $pixbufs{state}{disconnected}; } + $pixbuf; } + sub update_tray_icon() { if (!$ifw_alert || $img->get_storage_type ne 'pixbuf') { - my $pixbuf; - if ($current_state eq 'connected') { - if (detect_devices::is_wireless_interface($current_interface)) { - my $wnet = find { $_->{current} } values %wireless_networks; - $pixbuf = $pixbufs{link_level}{$wnet->{approx_level}} if $wnet; - } - $pixbuf ||= $pixbufs{state}{connected}; - } else { - $pixbuf = $pixbufs{state}{disconnected}; - } - $img->set_from_pixbuf($pixbuf); + $img->set_from_pixbuf(get_state_pixbuf()); } else { $img->set_from_stock('gtk-dialog-warning', 'small-toolbar'); } } -sub generate_menu { - my ($interface) = @_; + +sub enable_ifw_alert() { + unless ($ifw_alert) { + $ifw_alert = 1; + update_tray_icon(); + Glib::Timeout->add(1000, sub { + update_tray_icon(); + $ifw_alert; + }); + } +} + +sub disable_ifw_alert() { + eval { $ifw->send_alert_ack }; + $ifw_alert = 0; + update_tray_icon(); +} + +sub update_applet() { + $wireless_device = detect_devices::get_wireless_interface(); + + generate_simple_menu(); + generate_menu(); update_tray_icon(); - gtkset_tip(Gtk2::Tooltips->new, $eventbox, formatAlaTeX(sprintf(translate($tooltips{$current_state}), $interface))); - - my $menu = Gtk2::Menu->new; - my $create_item = sub { - my ($action) = @_; - my $name = ref($actions{$action}{name}) eq 'CODE' ? $actions{$action}{name}->($interface) : $actions{$action}{name}; - my $launch = $actions{$action}{launch}; - my @choices = exists $actions{$action}{choices} ? $actions{$action}{choices}->() : (); - my $w; - if (@choices == 0) { - $w = gtksignal_connect(gtkshow(Gtk2::MenuItem->new_with_label($name)), activate => sub { $launch->($interface) }); - } elsif (@choices > 1) { - my $selected = $actions{$action}{choice_selected}; - my $format = $actions{$action}{format_choice}; - $w = gtkshow(create_menu($name, map { - my $choice = $_; - my $w = gtkshow(gtkset_active(Gtk2::CheckMenuItem->new_with_label($format ? $format->($choice) : $choice), $selected->($choice))); - gtksignal_connect($w, activate => sub { $launch->($choice) }); - $w->set_draw_as_radio(!$actions{$action}{use_checkbox}); - $w; - } $actions{$action}{choices}->())); - } - #- don't add submenu if only one choice exists + gtkset_tip(Gtk2::Tooltips->new, $eventbox, get_state_message()); #gtkset($eventbox, tip => get_state_message()); +} + +sub create_menu_choices { + my ($action) = @_; + my @choices = $actions{$action}{choices}->(); + #- don't add submenu if only zero or one choice exists + @choices > ($actions{$action}{allow_single_choice} ? 0 : 1) or return (); + my $selected = $actions{$action}{choice_selected}; + my $format = $actions{$action}{format_choice}; + my $get_icon = $actions{$action}{get_icon}; + map { + my $choice = $_; + my $label = $format ? $format->($choice) : $choice; + my $w = gtkshow(gtkset_active(gtkadd( + Gtk2::CheckMenuItem->new, + gtknew('HBox', children => [ + 1, gtkset_alignment(gtknew('Label', text => $label), 0, 0.5), + $get_icon ? + (0, gtknew('Image', file => $get_icon->($_))) : + (), + ])), $selected->($choice))); + gtksignal_connect($w, activate => sub { $actions{$action}{launch}->($choice) }); + $w->set_draw_as_radio(!$actions{$action}{use_checkbox}); $w; - }; + } $actions{$action}{choices}->(); +} + +sub create_action_item { + my ($action) = @_; + my $name = ref($actions{$action}{name}) eq 'CODE' ? $actions{$action}{name}->($current_interface) : $actions{$action}{name}; + if (exists $actions{$action}{choices}) { + gtkshow(create_menu($name, + if_($actions{$action}{header}, + create_action_item($actions{$action}{header}), + gtkshow(Gtk2::SeparatorMenuItem->new), + ), + create_menu_choices($action), + )); + } else { + gtksignal_connect(gtkshow(Gtk2::MenuItem->new_with_label($name)), activate => sub { $actions{$action}{launch}->($current_interface) }); + } +} + +sub empty_menu { + my ($menu) = @_; + delete $_->{menuitems} foreach values %wireless_networks; + $menu->destroy if $menu; + Gtk2::Menu->new; +} + +sub get_wireless_networks_sorted() { + sort { + $b->{signal_strength} <=> $a->{signal_strength} || $a->{name} cmp $b->{name}; + } values %wireless_networks; +} + +sub generate_simple_menu() { + $simple_menu = empty_menu($simple_menu); + + if ($wireless_device) { + my @networks = get_wireless_networks_sorted(); + my @valuable_networks = splice @networks, 0, 7; + gtkappend($simple_menu, + (map { generate_wireless_menuitem($_) } @valuable_networks), + (@networks ? create_menu(N("More networks"), map { generate_wireless_menuitem($_) } @networks) : ()), + Gtk2::SeparatorMenuItem->new, + ); + } + gtkappend($simple_menu, create_menu_choices('setInterface')); +} + +sub generate_menu() { + $menu = empty_menu($menu); my (@settings); my $interactive; eval { $interactive = $ifw->get_interactive }; if ($current_state eq 'connected') { - $menu->append($create_item->($_)) foreach qw(downNetwork monitorNetwork); + $menu->append(create_action_item($_)) foreach qw(downNetwork monitorNetwork); } elsif ($current_state eq 'disconnected') { - $menu->append($create_item->('upNetwork')); + $menu->append(create_action_item('upNetwork')); } - $menu->append($create_item->('monitorIFW')) if $current_state ne 'notconfigured' && defined $interactive; + $menu->append(create_action_item('monitorIFW')) if $current_state ne 'notconfigured' && defined $interactive; - $menu->append($create_item->('confNetwork')); + $menu->append(create_action_item('confNetwork')); - if ($current_state ne 'notconfigured') { - $menu->append($create_item->('wireless')) if $wireless_device; - push @settings, $create_item->('chooseInterface'); - } + push @settings, create_action_item('chooseInterface') if $current_state ne 'notconfigured'; - push @settings, $create_item->('chooseProfile'); + push @settings, create_action_item('chooseProfile'); if (defined $interactive) { $interactive_cb = gtkshow(gtksignal_connect(gtkset_active(Gtk2::CheckMenuItem->new_with_label(N("Interactive Firewall automatic mode")), !$interactive), @@ -338,13 +475,18 @@ sub generate_menu { toggled => sub { setAutoStart(uc(bool2text($_[0]->get_active))) })); $menu->append(gtkshow(Gtk2::SeparatorMenuItem->new)); - $wireless_device and $menu->append(gtkshow($wireless_menu = create_menu(N("Wireless networks"), - map { $_->{menuitem} } values %wireless_networks))); - if (my $set = $current_state ne 'notconfigured' && $create_item->('setInterface')) { $menu->append($set) } - $menu->append(gtkshow(create_menu(N("Settings"), grep { $_ } @settings))); + if ($current_state ne 'notconfigured' && $wireless_device) { + $menu->append(gtkshow(create_menu(N("Wireless networks"), + create_action_item('wireless'), + gtkshow(Gtk2::SeparatorMenuItem->new), + map { generate_wireless_menuitem($_) } get_wireless_networks_sorted()))); + } + if (my $vpn = create_action_item('chooseVPN')) { $menu->append($vpn) } + if (my $set = $current_state ne 'notconfigured' && create_action_item('setInterface')) { $menu->append($set) } + $menu->append(gtkshow(create_menu(N("Settings"), @settings))); $menu->append(gtkshow(Gtk2::SeparatorMenuItem->new)); - $menu->append($create_item->('help')); - $menu->append($create_item->('quit')); + $menu->append(create_action_item('help')); + $menu->append(create_action_item('quit')); $menu; } sub mainQuit() { @@ -363,27 +505,17 @@ sub setAutoStart { ); } -sub get_unprocessed_attacks() { +sub get_unprocessed_ifw_messages() { my @packets = eval { $ifw->get_reports }; - while (my @attack = splice(@packets, 0, 10)) { - handle_attack(@attack); + while (my @ifw_message = splice(@packets, 0, 10)) { + handle_ifw_message(@ifw_message); } } -sub handle_attack { - my $attack = network::ifw::attack_to_hash(\@_); - push @attacks_queue, $attack; - @attacks_queue == 1 and notify_attack($attacks_queue[0]); -} - sub set_verdict { my ($attack, $apply_verdict) = @_; eval { $apply_verdict->($attack) }; $@ and err_dialog(N("Interactive Firewall"), N("Unable to contact daemon")); - - shift @attacks_queue; - #- wait for some time so that the new bubble is noticeable - @attacks_queue and Glib::Timeout->add(500, sub { notify_attack($attacks_queue[0]); 0 }); } sub apply_verdict_blacklist { @@ -402,33 +534,40 @@ sub apply_verdict_whitelist { apply_verdict_ignore($attack); } -sub notify_attack { - my ($attack) = @_; +sub handle_ifw_message { + my $attack = network::ifw::attack_to_hash(\@_); unless ($attack->{msg}) { print "unhandled attack type, skipping\n"; return; } - unless ($ifw_alert) { - $ifw_alert = 1; - update_tray_icon(); - Glib::Timeout->add(1000, sub { - update_tray_icon(); - $ifw_alert; - }); - } - $bubble->set(N("Interactive Firewall"), Gtk2::Image->new_from_pixbuf($pixbufs{firewall}), $attack->{msg}); - $bubble->show(5000); + enable_ifw_alert(); + $bubble_queue->add({ + title => N("Interactive Firewall"), + pixbuf => $pixbufs{firewall}, + message => $attack->{msg}, + timeout => sub { + set_verdict($attack, \&apply_verdict_ignore); + }, + clicked => sub { + disable_ifw_alert(); + ask_attack_verdict($attack); + }, + }); } sub ask_attack_verdict { my ($attack) = @_; my $w = ugtk2->new(N("Interactive Firewall: intrusion detected"), - icon => "/usr/lib/libDrakX/icons/drakfirewall.png"); + icon => "drakfirewall.png"); my ($blacklist, $whitelist, $ignore, $auto); my $update_automatic_mode = sub { $auto->get_active and $interactive_cb->set_active(1) }; - + my $set_verdict = sub { + my ($verdict) = @_; + set_verdict($attack, $verdict); + $bubble_queue->process_next; + }; gtkadd($w->{window}, gtknew('VBox', spacing => 5, children_loose => [ gtknew('HBox', children => [ @@ -467,23 +606,63 @@ sub ask_attack_verdict { $blacklist = gtknew('Button', text => N("Blacklist"), clicked => sub { $w->destroy; $update_automatic_mode->(); - set_verdict($attack, \&apply_verdict_blacklist); + $set_verdict->(\&apply_verdict_blacklist); }), $whitelist = gtknew('Button', text => N("Whitelist"), clicked => sub { $w->destroy; $update_automatic_mode->(); - set_verdict($attack, \&apply_verdict_whitelist); + $set_verdict->(\&apply_verdict_whitelist); }), $ignore = gtknew('Button', text => N("Ignore"), clicked => sub { $w->destroy; - set_verdict($attack, \&apply_verdict_ignore); + $set_verdict->(\&apply_verdict_ignore); }), ]), ])); eval { $auto->set_active(!$ifw->get_interactive) }; $blacklist->grab_focus; gtksignal_connect($w->{window}, delete_event => sub { - set_verdict($attack, \&apply_verdict_ignore); + $set_verdict->(\&apply_verdict_ignore); }); $w->{window}->show_all; } + +sub handle_ifw_listen { + my $listen = network::ifw::parse_listen_message(\@_); + enable_ifw_alert(); + $bubble_queue->add({ + title => N("Interactive Firewall: new service"), + pixbuf => $pixbufs{firewall}, + message => $listen->{message}, + clicked => 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.png"); + my $set_verdict = sub { + $bubble_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; +} diff --git a/bin/net_monitor b/bin/net_monitor index b513b54..b9ca3de 100755 --- a/bin/net_monitor +++ b/bin/net_monitor @@ -2,7 +2,7 @@ # NetMonitor -# Copyright (C) 1999-2005 Mandriva +# Copyright (C) 1999-2006 Mandriva # Damien "Dam's" Krotkine # Thierry Vignaud <tvignaud@mandriva.com> # @@ -23,10 +23,13 @@ use lib qw(/usr/lib/libDrakX); use strict; +# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX) +BEGIN { unshift @::textdomains, 'drakx-net' } use standalone; #- warning, standalone must be loaded very first, for 'explanations' use c; use interactive; +use mygtk2 qw(gtknew gtkset); use ugtk2 qw(:create :helpers :wrappers); use common; use network::network; @@ -86,38 +89,38 @@ my %config = getVarsFromSh($cfg_file); my $use_same_scale = text2bool($config{use_same_scale}); gtkadd($window1->{window}, - gtkpack_(Gtk2::VBox->new(0,5), - 1, gtkpack_(Gtk2::HBox->new(0,5), - 0, my $notebook = Gtk2::Notebook->new, - 1, gtkpack_(Gtk2::VBox->new(0,5), - 0, gtkadd(gtkset_shadow_type(Gtk2::Frame->new(N("Settings")), 'etched_out'), - gtkpack__(gtkset_border_width(Gtk2::HBox->new(0,0),5), + gtknew('VBox', spacing => 5, children => [ + 1, gtknew('HBox', spacing => 5, children => [ + 0, my $notebook = gtknew('Notebook'), + 1, gtknew('VBox', spacing => 5, children => [ + 0, gtknew('Frame', text => N("Settings"), shadow_type => 'etched_out', child => + gtknew('HBox', border_width => 5, children_tight => [ N("Connection type: "), - my $label_cnx_type = Gtk2::Label->new("")), + my $label_cnx_type = gtknew('Label', text => "")]), ), - 1, gtkadd(gtkset_shadow_type(Gtk2::Frame->new(N("Global statistics")), 'etched_out'), - gtkpack__(gtkset_border_width(Gtk2::VBox->new(0,0),5), - create_packtable({ col_spacings => 1, row_spacings => 5, homogeneous => 1 }, - [ Gtk2::Label->new(""), Gtk2::Label->new(N("Instantaneous")) , Gtk2::Label->new(N("Average")) ], - [ Gtk2::WrappedLabel->new(N("Sending\nspeed:")), my $label_st = Gtk2::Label->new(""), my $label_sta = Gtk2::Label->new(N("unknown")) ], - [ Gtk2::WrappedLabel->new(N("Receiving\nspeed:")), my $label_sr = Gtk2::Label->new(""), my $label_sra = Gtk2::Label->new(N("unknown")) ], - ), - Gtk2::HSeparator->new, - gtkpack__(gtkset_border_width(Gtk2::HBox->new(0,0),5), + 1, gtknew('Frame', text => N("Global statistics"), shadow_type => 'etched_out', child => + gtknew('VBox', border_width => 5, children_tight => [ + gtknew('Table', col_spacings => 1, row_spacings => 5, homogeneous => 1, children => [ + [ gtknew('Label', text => ""), gtknew('Label', text => N("Instantaneous")) , gtknew('Label', text => N("Average")) ], + [ gtknew('WrappedLabel', text => N("Sending\nspeed:")), my $label_st = gtknew('Label', text => ""), my $label_sta = gtknew('Label', text => N("unknown")) ], + [ gtknew('WrappedLabel', text => N("Receiving\nspeed:")), my $label_sr = gtknew('Label', text => ""), my $label_sra = gtknew('Label', text => N("unknown")) ], + ]), + gtknew('HSeparator'), + gtknew('HBox', border_width => 5, children_tight => [ N("Connection\ntime: "), - my $label_ct = Gtk2::Label->new(N("unknown")), - ), - ) + my $label_ct = gtknew('Label', text => N("unknown")), + ]), + ]) ), - ) - ), - 0, gtksignal_connect(gtkset_active(Gtk2::CheckButton->new(N("Use same scale for received and transmitted")), $use_same_scale), clicked => sub { $use_same_scale = !$use_same_scale }), - 0, gtkpack(create_hbox('edge'), - gtksignal_connect(my $button_connect = gtkset_sensitive(Gtk2::Button->new(N("Wait please")), 0), clicked => \&connection), - gtksignal_connect(my $button_close = Gtk2::Button->new(N("Close")), clicked => \&main_quit), - ), + ]) + ]), + 0, gtksignal_connect(gtkset_active(gtknew('CheckButton', text => N("Use same scale for received and transmitted")), $use_same_scale), clicked => sub { $use_same_scale = !$use_same_scale }), + 0, gtknew('HButtonBox', layout => 'edge', children_loose => [ + my $button_connect = gtknew('Button', text => N("Wait please"), sensitive => 0, clicked => \&connection), + my $button_close = gtknew('Button', text => N("Close"), clicked => \&main_quit), + ]), 0, my $statusbar = Gtk2::Statusbar->new - ), + ]), ); $window1->{window}->show_all; @@ -185,7 +188,7 @@ sub connection() { $ct_tag = Glib::Timeout->add(1000, sub { my ($sec, $min, $hour) = gmtime(time() - $c_time); my $e = sprintf("%02d:%02d:%02d", $hour, $min, $sec); - $label_ct->set_label($e); 1 }); + gtkset($label_ct, text => $e); 1 }); } my $nb_point = 1; $first = 1; @@ -295,19 +298,19 @@ sub rescan() { draw_monitor($monitor->{$intf}, $intf); } - $label_sr->set_label(formatXiB($monitor->{sr}) . "/s"); - $label_st->set_label(formatXiB($monitor->{st}) . "/s"); + gtkset($label_sr, text => formatXiB($monitor->{sr}) . "/s"); + gtkset($label_st, text => formatXiB($monitor->{st}) . "/s"); $monitor->{sra} += $monitor->{sr}; $monitor->{sta} += $monitor->{st}; $monitor->{nba}++; if ($monitor->{nba} > 9) { - $label_sra->set_label(formatXiB($monitor->{sra}/10) . "/s"); - $label_sta->set_label(formatXiB($monitor->{sta}/10) . "/s"); + gtkset($label_sra, text => formatXiB($monitor->{sra}/10) . "/s"); + gtkset($label_sta, text => formatXiB($monitor->{sta}/10) . "/s"); $monitor->{sra} = 0; $monitor->{sta} = 0; $monitor->{nba} = 0; } - $label_cnx_type->set_label(translate($net->{type})); + gtkset($label_cnx_type, text => translate($net->{type})); $monitor->{$_} = 0 foreach 'sr', 'st'; 1; } @@ -351,6 +354,19 @@ $scale_r = $scale_t = $height; sub scale_tranmistted($) { $_[0] * $scale_t } sub scale_received($) { $_[0] * $scale_r } +sub color_button { + my ($gc, $color) = @_; + gtknew('Button', relief => 'none', clicked => sub { + $color = change_color($color); + $gc->set_rgb_fg_color($color); + $_[0]->queue_draw; + }, + child => gtksignal_connect(gtkshow(gtksize(gtkset(Gtk2::DrawingArea->new, width => 10, height => 10), 10, 10)), + expose_event => sub { $_[0]->window->draw_rectangle($gc, 1, 0, 0, 10, 10) }) + ); +} + + sub update() { if (!$during_connection) { my $isconnect = test_connected(0); @@ -369,54 +385,38 @@ sub update() { $monitor->{$intf}{initialt} = $monitor->{$intf}{val}[8]; $darea->{$intf} = Gtk2::DrawingArea->new; $darea->{$intf}->set_events(["pointer_motion_mask"]); - $notebook->append_page(gtkshow(my $page = gtkpack_(Gtk2::VBox->new(0,0), - 0, gtkpack__(gtkset_border_width(Gtk2::HBox->new(0,0), 5), - gtksize($darea->{$intf}, $width, $height)), - 0, gtkpack_(Gtk2::HBox->new(0,0), - 1, gtkpack__(Gtk2::VBox->new(0,0), - gtkpack__(gtkset_border_width(Gtk2::HBox->new(0,5), 5), - gtksignal_connect(my $button_t = gtkset_relief(Gtk2::Button->new, 'none'), clicked => sub { - $colort = change_color($colort); - $gct->set_foreground($colort); - $_[0]->queue_draw; - }), - N("sent: "), $monitor->{$intf}{labelt} = Gtk2::Label->new("0")), - gtkpack__(gtkset_border_width(Gtk2::HBox->new(0,5), 5), - gtksignal_connect(my $button_r = gtkset_relief(Gtk2::Button->new, 'none'), clicked => sub { - $colorr = change_color($colorr); - $gcr->set_foreground($colorr); - $_[0]->queue_draw; - }), - N("received: "), $monitor->{$intf}{labelr} = Gtk2::Label->new("0")), - gtkpack__(gtkset_border_width(Gtk2::HBox->new(0,5), 5), - gtksignal_connect(my $button_a = gtkset_relief(Gtk2::Button->new, 'none'), clicked => sub { - $colora = change_color($colora); - $gca->set_foreground($colora); - $_[0]->queue_draw; - }), - N("average")) - ), - 0, gtkpack__(gtkset_border_width(Gtk2::VBox->new(0,0), 5), - gtkadd(gtkset_shadow_type(Gtk2::Frame->new(N("Local measure")), 'etched_out'), - gtkpack__(gtkset_border_width(Gtk2::VBox->new(0,0), 5), - gtkpack__(Gtk2::HBox->new(0,0), + $notebook->append_page(gtkshow(my $page = gtknew('VBox', children => [ + 0, gtknew('HBox', border_width => 5, children_tight => [ + gtksize($darea->{$intf}, $width, $height)]), + 0, gtknew('HBox', children => [ + 1, gtknew('VBox', children_tight => [ + gtknew('HBox', spacing => 5, border_width => 5, children_tight => [ + color_button($gct, $colort), + N("sent: "), $monitor->{$intf}{labelt} = gtknew('Label', text => "0")]), + gtknew('HBox', spacing => 5, border_width => 5, children_tight => [ + color_button($gcr, $colorr), + N("received: "), $monitor->{$intf}{labelr} = gtknew('Label', text => "0")]), + gtknew('HBox', spacing => 5, border_width => 5, children_tight => [ + color_button($gca, $colora), + N("average")]) + ]), + 0, gtknew('VBox', border_width => 5, children_tight => [ + gtknew('Frame', text => N("Local measure"), shadow_type => 'etched_out', child => + gtknew('VBox', border_width => 5, children_tight => [ + gtknew('HBox', children_tight => [ N("sent: "), - my $measure_t = Gtk2::Label->new("0") - ), - gtkpack__(Gtk2::HBox->new(0,0), + my $measure_t = gtknew('Label', text => "0") + ]), + gtknew('HBox', children_tight => [ N("received: "), - my $measure_r = Gtk2::Label->new("0") - ) - ) + my $measure_r = gtknew('Label', text => "0") + ]) + ]) ) - ) - ) - )), - Gtk2::Label->new($intf)); - foreach my $i ([$button_t, $gct], [$button_r, $gcr], [$button_a, $gca]) { - $i->[0]->add(gtksignal_connect(gtkshow(gtksize(gtkset_size_request(Gtk2::DrawingArea->new, 10, 10), 10, 10)), - expose_event => sub { $_[0]->window->draw_rectangle($i->[1], 1, 0, 0, 10, 10) })); - } + ]) + ]) + ])), + gtknew('Label', text => $intf)); $monitor->{$intf}{page} = $notebook->page_num($page); $darea->{$intf}->realize; $pixmap->{$intf} = Gtk2::Gdk::Pixmap->new($darea->{$intf}->window, $width, $height, $darea->{$intf}->window->get_depth); @@ -428,8 +428,8 @@ sub update() { my $x = $e->x - 50; my $received = $x >= 0 ? $monitor->{$intf}{stack_r}[$x] : 0; my $transmitted = $x >= 0 ? $monitor->{$intf}{stack_t}[$x] : 0; - $measure_r->set_label(formatXiB($received)); - $measure_t->set_label(formatXiB($transmitted)); + gtkset($measure_r, text => formatXiB($received)); + gtkset($measure_t, text => formatXiB($transmitted)); }); $darea->{$intf}->signal_connect(expose_event => sub { $darea->{$intf}->window->draw_drawable($darea->{$intf}->style->bg_gc('normal'), $pixmap->{$intf}, 0, 0, 0, 0, $width, $height); |