1 |
package network::connection; |
2 |
|
3 |
use common; |
4 |
use network::vpn; |
5 |
|
6 |
sub get_types { |
7 |
sort { $a->get_metric <=> $b->get_metric } grep { $_->can('get_devices') } common::load_modules_from_base(__PACKAGE__); |
8 |
} |
9 |
|
10 |
=item get_type_name() |
11 |
|
12 |
Get the connection type name, unstranslated |
13 |
|
14 |
=cut |
15 |
|
16 |
sub get_type_name() { N("Unknown connection type") } |
17 |
sub get_type_description { |
18 |
my ($class) = @_; |
19 |
$class->get_type_name; |
20 |
} |
21 |
|
22 |
=item get_type_icon() |
23 |
|
24 |
Get the connection type icon path |
25 |
|
26 |
=cut |
27 |
|
28 |
sub get_type_icon { |
29 |
my ($self, $o_size) = @_; |
30 |
my $size = $o_size || 24; |
31 |
my $icon = eval { $self->_get_type_icon . '-' . $size }; |
32 |
$icon || '/usr/share/mcc/themes/default/drakconnect-mdk'; |
33 |
} |
34 |
|
35 |
=item get_devices(%options) |
36 |
|
37 |
Get the devices supported by this connection type |
38 |
Options: |
39 |
- automatic_only (no device requiring manual configuration should be returned) |
40 |
- fast_only (no slow detection should be performed) |
41 |
|
42 |
=cut |
43 |
|
44 |
=item get_connections(%options) |
45 |
|
46 |
List connections that can be configured by the class |
47 |
Options: see get_devices() |
48 |
|
49 |
=cut |
50 |
|
51 |
sub get_connections { |
52 |
my ($class, %options) = @_; |
53 |
map { $class->new($_) } $class->get_devices(%options); |
54 |
} |
55 |
|
56 |
=item find_ifcfg_type($ifcfg) |
57 |
|
58 |
Returns the class matching the connection type of the ifcfg hash |
59 |
|
60 |
=cut |
61 |
|
62 |
sub find_ifcfg_type { |
63 |
my ($_class, $ifcfg) = @_; |
64 |
find { $_->can('handles_ifcfg') && $_->handles_ifcfg($ifcfg) } sort { $b->get_metric <=> $a->get_metric } get_types(); |
65 |
} |
66 |
|
67 |
sub new { |
68 |
my ($class, $device) = @_; |
69 |
bless { |
70 |
device => $device, |
71 |
networks => {}, |
72 |
}, $class; |
73 |
} |
74 |
|
75 |
sub get_description { |
76 |
my ($self) = @_; |
77 |
my $description = $self->{device}{description}; |
78 |
$description =~ s/\|/ /g; |
79 |
$description; |
80 |
} |
81 |
|
82 |
sub get_label { |
83 |
my ($self) = @_; |
84 |
my $intf = $self->get_interface; |
85 |
my $descr = $self->get_description; |
86 |
$intf ? sprintf("%s (%s)", $descr, $intf) : $descr; |
87 |
} |
88 |
|
89 |
sub get_driver { |
90 |
my ($self) = @_; |
91 |
$self->{device}{driver}; |
92 |
} |
93 |
|
94 |
sub get_interface { |
95 |
my ($_self) = @_; |
96 |
die "unable to get interface"; |
97 |
} |
98 |
|
99 |
sub get_metric { 60 } |
100 |
|
101 |
sub get_up_timeout { 10 } |
102 |
|
103 |
sub get_status { |
104 |
my ($self) = @_; |
105 |
require network::tools; |
106 |
my ($_is_up, $gw_address) = network::tools::get_interface_status($self->get_interface); |
107 |
$self->{status} = to_bool($gw_address); |
108 |
} |
109 |
|
110 |
=item get_status_icon() |
111 |
|
112 |
Get status icon path (connected/disconnected/unconfigured) |
113 |
The file may not exist |
114 |
|
115 |
=cut |
116 |
|
117 |
sub get_status_icon { |
118 |
my ($self) = @_; |
119 |
my $icon = $self->get_type_icon; |
120 |
my $status = $self->get_interface ? $self->get_status ? "on" : "off" : "w"; |
121 |
$icon . "-" . $status; |
122 |
} |
123 |
|
124 |
sub get_ifcfg_bool { |
125 |
my ($self, $field) = @_; |
126 |
defined $self->{ifcfg}{$field} ? text2bool($self->{ifcfg}{$field}) : undef; |
127 |
} |
128 |
|
129 |
sub get_selected_network { |
130 |
my ($self) = @_; |
131 |
exists $self->{networks}{$self->{network}} && $self->{networks}{$self->{network}}; |
132 |
} |
133 |
|
134 |
sub selected_network_is_configured { |
135 |
my ($self) = @_; |
136 |
|
137 |
my $network = $self->get_selected_network or return; |
138 |
$self->network_is_configured($network); |
139 |
} |
140 |
|
141 |
sub load_interface_settings { |
142 |
my ($self) = @_; |
143 |
require network::network; |
144 |
my $file = network::network::get_ifcfg_file($self->get_interface); |
145 |
$self->{ifcfg} = { getVarsFromSh($file) }; |
146 |
$self->{vpn_list} = [ map { $_->get_configured_connections } network::vpn->list_types ]; |
147 |
$self->{control}{onboot} = $self->get_ifcfg_bool('ONBOOT'); |
148 |
$self->{control}{userctl} = $self->get_ifcfg_bool('USERCTL'); |
149 |
$self->{control}{metric} = $self->{ifcfg}{METRIC}; |
150 |
$self->{control}{mtu} = $self->{ifcfg}{MTU}; |
151 |
$self->{control}{macaddr} = $self->{ifcfg}{MACADDR}; |
152 |
$self->{control}{hwaddr} = $self->{ifcfg}{HWADDR}; |
153 |
$self->{control}{ethtool_opts} = $self->{ifcfg}{ETHTOOL_OPTS}; |
154 |
$self->{control}{accounting} = $self->get_ifcfg_bool('ACCOUNTING'); |
155 |
$self->{control}{nm_controlled} = $self->get_ifcfg_bool('NM_CONTROLLED'); |
156 |
$self->{control}{uuid} = $self->{ifcfg}{UUID}; |
157 |
$self->{control}{name} = $self->{ifcfg}{NAME}; |
158 |
$self->{control}{last_connect} = $self->{ifcfg}{LAST_CONNECT}; |
159 |
} |
160 |
|
161 |
#- override to return 1 if the connection network scan is slow |
162 |
sub network_scan_is_slow { 0 } |
163 |
#- override to return 1 if the hardware check is slow |
164 |
sub check_hardware_is_slow { 0 } |
165 |
#- override to return 1 if only one network is supported |
166 |
sub has_unique_network { 0 } |
167 |
|
168 |
sub get_network_access_settings_label { N("Network access settings") } |
169 |
sub get_access_settings_label { N("Access settings") } |
170 |
sub get_address_settings_label { N("Address settings") } |
171 |
|
172 |
#- check that $self->can('get_providers') first |
173 |
sub guess_provider_settings { |
174 |
my ($self) = @_; |
175 |
require lang; |
176 |
my @providers_data = $self->get_providers; |
177 |
my $locale_country = lang::c2name(ref($::o) && $::o->{locale}{country} || lang::read()->{country}); |
178 |
my $separator = $providers_data[1]; |
179 |
$self->{provider_name} ||= find { /^\Q$locale_country$separator\E/ } sort(keys %{$providers_data[0]}); |
180 |
} |
181 |
|
182 |
sub set_provider { |
183 |
my ($self, $net) = @_; |
184 |
if ($self->{provider_name} ne N("Unlisted - edit manually")) { |
185 |
my @providers_data = $self->get_providers; |
186 |
$self->{provider} = $providers_data[0]{$self->{provider_name}}; |
187 |
$self->apply_provider_settings($net); |
188 |
} |
189 |
} |
190 |
|
191 |
sub apply_provider_settings { |
192 |
my ($self, $net) = @_; |
193 |
$self->guess_protocol($net) if $self->can('guess_protocol'); |
194 |
$self->guess_access_settings('provider_only') if $self->can('guess_access_settings'); |
195 |
} |
196 |
|
197 |
#- check that $self->can('get_providers') first |
198 |
sub get_provider_settings { |
199 |
my ($self, $net) = @_; |
200 |
my @providers_data = $self->get_providers; |
201 |
[ |
202 |
{ |
203 |
type => "list", val => \$self->{provider_name}, separator => $providers_data[1], |
204 |
list => [ N("Unlisted - edit manually"), sort(keys %{$providers_data[0]}) ], sort => 0, |
205 |
changed => sub { $self->set_provider($net) }, |
206 |
}, |
207 |
]; |
208 |
} |
209 |
|
210 |
#- check that $self->can('get_protocols') first |
211 |
sub get_protocol_settings { |
212 |
my ($self) = @_; |
213 |
my $protocols = $self->get_protocols; |
214 |
[ |
215 |
{ |
216 |
val => \$self->{protocol}, type => 'list', |
217 |
list => [ sort { $protocols->{$a} cmp $protocols->{$b} } keys %$protocols ], |
218 |
format => sub { $protocols->{$_[0]} }, |
219 |
} |
220 |
]; |
221 |
} |
222 |
|
223 |
sub guess_network_control_settings { |
224 |
my ($self) = @_; |
225 |
$self->{control}{vpn} = find { |
226 |
$self->{ifcfg}{VPN_TYPE} eq $_->get_type && |
227 |
$self->{ifcfg}{VPN_NAME} eq $_->get_name; |
228 |
} @{$self->{vpn_list}}; |
229 |
} |
230 |
|
231 |
sub get_network_control_settings { |
232 |
my ($self) = @_; |
233 |
[ |
234 |
if_(@{$self->{vpn_list}}, |
235 |
{ label => N("VPN connection"), val => \$self->{control}{vpn}, |
236 |
list => [ undef, @{$self->{vpn_list}} ], |
237 |
format => sub { defined $_[0] ? $_[0]->get_label : N("None") } }), |
238 |
]; |
239 |
} |
240 |
|
241 |
sub guess_control_settings { |
242 |
my ($self) = @_; |
243 |
$self->{control}{metric} ||= $self->get_metric; |
244 |
} |
245 |
|
246 |
sub get_control_settings { |
247 |
my ($self) = @_; |
248 |
[ |
249 |
{ text => N("Allow users to manage the connection"), val => \$self->{control}{userctl}, type => "bool" }, |
250 |
{ text => N("Start the connection at boot"), val => \$self->{control}{onboot}, type => "bool" }, |
251 |
{ text => N("Enable traffic accounting"), val => \$self->{control}{accounting}, type => "bool" }, |
252 |
{ text => N("Allow interface to be controlled by Network Manager"), val => \$self->{control}{nm_controlled}, type => "bool" }, |
253 |
{ label => N("Metric"), val => \$self->{control}{metric}, advanced => 1 }, |
254 |
{ label => N("MTU"), val => \$self->{control}{mtu}, advanced => 1, |
255 |
help => N("Maximum size of network message (MTU). If unsure, left blank.") }, |
256 |
{ label => N("Fake make address (MACADDR)"), val => \$self->{control}{macaddr}, advanced => 1, |
257 |
help => N("Use a fake MAC address. If unset, uses HWADDR or default.") }, |
258 |
{ label => N("MAC address (HWADDR)"), val => \$self->{control}{hwaddr}, advanced => 1, |
259 |
help => N("Make sure to bind the interface to the network card with that MAC address. If unset, uses default.") }, |
260 |
{ label => N("Ethtool options"), val => \$self->{control}{ethtool_opts}, advanced => 1, |
261 |
help => N("Use ethtool to pass options to the NIC. eg. \"autoneg off wol g\"") }, |
262 |
]; |
263 |
} |
264 |
|
265 |
sub build_ifcfg_settings { |
266 |
my ($self, $o_options) = @_; |
267 |
put_in_hash($o_options, { |
268 |
DEVICE => $self->get_interface, |
269 |
ONBOOT => bool2yesno($self->{control}{onboot}), |
270 |
ACCOUNTING => bool2yesno($self->{control}{accounting}), |
271 |
NM_CONTROLLED => bool2yesno($self->{control}{nm_controlled}), |
272 |
USERCTL => bool2yesno($self->{control}{userctl}), |
273 |
METRIC => $self->{control}{metric}, |
274 |
MTU => $self->{control}{mtu}, |
275 |
MACADDR => $self->{control}{macaddr}, |
276 |
HWADDR => $self->{control}{hwaddr}, |
277 |
ETHTOOL_OPTS => $self->{control}{ethtool_opts}, |
278 |
UUID => $self->{control}{uuid}, |
279 |
NAME => $self->{control}{name}, |
280 |
LAST_CONNECT => $self->{control}{last_connect}, |
281 |
VPN_TYPE => defined $self->{control}{vpn} && $self->{control}{vpn}->get_type, |
282 |
VPN_NAME => defined $self->{control}{vpn} && $self->{control}{vpn}->get_name, |
283 |
#- FIXME: add MS_DNSx variables if DNS servers are specified |
284 |
}); |
285 |
} |
286 |
|
287 |
sub write_settings { |
288 |
my ($self, $o_net, $_o_modules_conf) = @_; |
289 |
require network::network; |
290 |
my $file = network::network::get_ifcfg_file($self->get_interface); |
291 |
network::network::write_interface_settings($self->build_ifcfg_settings, $file); |
292 |
if ($self->{address}{hostname}) { |
293 |
$o_net->{network}{HOSTNAME} = $self->{address}{hostname} if $o_net; |
294 |
network::network::write_hostname($self->{address}{hostname}); |
295 |
} |
296 |
network::network::write_network_conf($o_net) if $o_net; |
297 |
require network::shorewall; |
298 |
network::shorewall::update_interfaces_list($self->get_interface); |
299 |
network::network::reload_net_applet(); |
300 |
} |
301 |
|
302 |
sub probed_networks { |
303 |
my ($self) = @_; |
304 |
$self->{probed_networks} = 1; |
305 |
} |
306 |
|
307 |
sub connect { |
308 |
my ($self) = @_; |
309 |
require network::tools; |
310 |
network::tools::start_interface($self->get_interface, 0); |
311 |
} |
312 |
|
313 |
sub disconnect { |
314 |
my ($self) = @_; |
315 |
require network::tools; |
316 |
network::tools::stop_interface($self->get_interface, 0); |
317 |
} |
318 |
|
319 |
sub setup_thirdparty { |
320 |
my ($self, $in) = @_; |
321 |
my $driver = $self->get_driver; |
322 |
# FIXME: weird return code |
323 |
$driver && $self->can('get_thirdparty_settings') or return 1; |
324 |
require network::thirdparty; |
325 |
$self->{thirdparty} = network::thirdparty::apply_settings($in, ref $self, $self->get_thirdparty_settings, $driver); |
326 |
$self->{device} = $self->{thirdparty}{device} if $self->{thirdparty} && $self->{thirdparty}{device}; |
327 |
$self->{thirdparty}; |
328 |
} |
329 |
|
330 |
sub prepare_device { |
331 |
my ($self) = @_; |
332 |
my $driver = $self->get_driver; |
333 |
if ($driver) { |
334 |
require modules; |
335 |
eval { modules::load($driver) }; |
336 |
} |
337 |
} |
338 |
|
339 |
#- status messages can be sent using mdv-network-event |
340 |
sub get_status_message { |
341 |
my ($self, $status) = @_; |
342 |
my $interface = $self->get_interface; |
343 |
{ |
344 |
link_up => N("Link detected on interface %s", $interface), |
345 |
link_down => N("Link beat lost on interface %s", $interface), |
346 |
}->{$status}; |
347 |
} |
348 |
|
349 |
=head2 Pure virtual private instance methods |
350 |
|
351 |
=over |
352 |
|
353 |
=item _get_type_icon |
354 |
|
355 |
Get the icon prefix for the connection type |
356 |
|
357 |
=back |
358 |
|
359 |
=cut |
360 |
|
361 |
1; |