diff options
Diffstat (limited to 'perl-install/network/wireless.pm')
-rw-r--r-- | perl-install/network/wireless.pm | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/perl-install/network/wireless.pm b/perl-install/network/wireless.pm new file mode 100644 index 000000000..96a607ce6 --- /dev/null +++ b/perl-install/network/wireless.pm @@ -0,0 +1,198 @@ +package network::wireless; + +use strict; +use common; +use modules; +use detect_devices; +use c; + +sub convert_wep_key_for_iwconfig { + #- 5 or 13 characters, consider the key as ASCII and prepend "s:" + #- else consider the key as hexadecimal, do not strip dashes + #- always quote the key as string + my ($key) = @_; + member(length($key), (5, 13)) ? "s:$key" : $key; +} + +sub get_wep_key_from_iwconfig { + #- strip "s:" if the key is 5 or 13 characters (ASCII) + #- else the key as hexadecimal, do not modify + my ($key) = @_; + $key =~ s/^s:// if member(length($key), (7,15)); + $key; +} + +sub convert_key_for_wpa_supplicant { + my ($key) = @_; + if ($key =~ /^([[:xdigit:]]{4}[\:-])+[[:xdigit:]]{2,}$/) { + $key =~ s/[\:-]//g; + return lc($key); + } else { + return qq("$key"); + } +} + +#- FIXME: to be improved (quotes, comments) and moved in common files +sub wlan_ng_update_vars { + my ($file, $vars) = @_; + substInFile { + while (my ($key, $value) = each(%$vars)) { + s/^#?\Q$key\E=(?:"[^#]*"|[^#\s]*)(\s*#.*)?/$key=$value$1/ and delete $vars->{$key}; + } + $_ .= join('', map { "$_=$vars->{$_}\n" } keys %$vars) if eof; + } $file; +} + +sub wlan_ng_configure { + my ($in, $ethntf, $module) = @_; + $in->do_pkgs->install('prism2-utils'); + if ($ethntf->{WIRELESS_ESSID}) { + my $wlan_conf_file = "$::prefix/etc/wlan/wlan.conf"; + my @wlan_devices = split(/ /, (cat_($wlan_conf_file) =~ /^WLAN_DEVICES="(.*)"/m)[0]); + push @wlan_devices, $ethntf->{DEVICE} unless member($ethntf->{DEVICE}, @wlan_devices); + #- enable device and make it use the choosen ESSID + wlan_ng_update_vars($wlan_conf_file, + { + WLAN_DEVICES => qq("@wlan_devices"), + "SSID_$ethntf->{DEVICE}" => qq("$ethntf->{WIRELESS_ESSID}"), + "ENABLE_$ethntf->{DEVICE}" => "y" + }); + my $wlan_ssid_file = "$::prefix/etc/wlan/wlancfg-$ethntf->{WIRELESS_ESSID}"; + #- copy default settings for this ESSID if config file does not exist + -f $wlan_ssid_file or cp_f("$::prefix/etc/wlan/wlancfg-DEFAULT", $wlan_ssid_file); + #- enable/disable encryption + wlan_ng_update_vars($wlan_ssid_file, + { + (map { $_ => $ethntf->{WIRELESS_ENC_KEY} ? "true" : "false" } qw(lnxreq_hostWEPEncrypt lnxreq_hostWEPDecrypt dot11PrivacyInvoked dot11ExcludeUnencrypted)), + AuthType => $ethntf->{WIRELESS_ENC_KEY} ? qq("sharedkey") : qq("opensystem"), + if_($ethntf->{WIRELESS_ENC_KEY}, + dot11WEPDefaultKeyID => 0, + dot11WEPDefaultKey0 => qq("$ethntf->{WIRELESS_ENC_KEY}") + ) + }); + #- hide settings for non-root users + chmod 0600, $wlan_conf_file; + chmod 0600, $wlan_ssid_file; + } + #- apply settings on wlan interface + require services; + services::restart($module eq 'prism2_cs' ? 'pcmcia' : 'wlan'); +} + +sub wpa_supplicant_get_driver { + my ($module) = @_; + $module =~ /^hostap_/ ? "hostap" : + $module eq "prism54" ? "prism54" : + $module =~ /^ath_/ ? "madwifi" : + $module =~ /^at76c50|atmel_/ ? "atmel" : + $module eq "ndiswrapper" ? "ndiswrapper" : + $module =~ /^ipw2[12]00$/ ? "ipw" : + "wext"; +} + +sub wpa_supplicant_configure { + my ($in, $ethntf) = @_; + require services; + $in->do_pkgs->install('wpa_supplicant'); + + wpa_supplicant_add_network({ + ssid => qq("$ethntf->{WIRELESS_ESSID}"), + psk => network::tools::convert_key_for_wpa_supplicant($ethntf->{WIRELESS_ENC_KEY}), + scan_ssid => 1, + }); +} + +sub wpa_supplicant_add_network { + my ($new_network) = @_; + my $wpa_supplicant_conf = "$::prefix/etc/wpa_supplicant.conf"; + my $s; + my %network; + foreach (cat_($wpa_supplicant_conf)) { + if (%network) { + #- in a "network = {}" block + if (/^\s*(\w+)=(.*?)(\s*#.*)?$/) { + push @{$network{entries}}, { key => $1, value => $2, comment => $3 }; + $1 eq 'ssid' and $network{ssid} = $2; + } elsif (/^\}/) { + #- end of network block, write it + $s .= "network={$network{comment}\n"; + my $update = $network{ssid} eq $new_network->{ssid}; + foreach (@{$network{entries}}) { + my $key = $_->{key}; + if ($update) { + #- do not write entry if not provided in the new network + exists $new_network->{$key} or next; + #- update value from the new network + $_->{value} = delete $new_network->{$key}; + } + if ($key) { + $s .= " $key=$_->{value}$_->{comment}\n"; + } else { + $s .= " $_->{comment}\n"; + } + } + if ($update) { + while (my ($key, $value) = each(%$new_network)) { + $s .= " $key=$value\n"; + } + } + $s .= "}\n"; + undef %network; + $update and undef $new_network; + } else { + #- unrecognized, keep it anyway + push @{$network{entries}}, { comment => $_ }; + } + } else { + if (/^\s*network={(.*)/) { + #- beginning of a new network block + $network{comment} = $1; + } else { + #- keep other options, comments + $s .= $_; + } + } + } + if ($new_network) { + #- network wasn't found, write it + $s .= "\nnetwork={\n"; + #- write ssid first + if (my $ssid = delete $new_network->{ssid}) { + $s .= " ssid=$ssid\n"; + } + while (my ($key, $value) = each(%$new_network)) { + $s .= " $key=$value\n"; + } + $s .= "}\n"; + } + output($wpa_supplicant_conf, $s); + #- hide keys for non-root users + chmod 0600, $wpa_supplicant_conf; +} + +sub ndiswrapper_installed_drivers() { + `ndiswrapper -l` =~ /(\w+)\s+driver present/mg; +} + +sub ndiswrapper_available_drivers() { + `ndiswrapper -l` =~ /(\w+)\s+driver present, hardware present/mg; +} + +sub ndiswrapper_setup() { + eval { modules::unload("ndiswrapper") }; + #- unload ndiswrapper first so that the newly installed .inf files will be read + eval { modules::load("ndiswrapper") }; + + #- FIXME: move this somewhere in get_eth_cards, so that configure_eth_aliases correctly writes ndiswrapper + #- find the first interface matching an ndiswrapper driver, try ethtool then sysfs + my @available_drivers = ndiswrapper_available_drivers(); + my $ntf_name = find { + my $drv = c::getNetDriver($_) || readlink("/sys/class/net/$_/driver"); + $drv =~ s!.*/!!; + member($drv, @available_drivers); + } detect_devices::getNet(); + #- fallback on wlan0 + return $ntf_name || "wlan0"; +} + +1; |