package network::wireless; use strict; use common; 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 ($real_key, $restricted) = @_; my $key = member(length($real_key), (5, 13)) ? "s:$real_key" : $real_key; $restricted ? "restricted $key" : "open $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)); my ($mode, $real_key) = $key =~ /^(?:(open|restricted)\s+)?(.*)$/; ($real_key, $mode eq 'restricted'); } sub convert_key_for_wpa_supplicant { my ($key) = @_; if ($key =~ /^([[:xdigit:]]{4}[\:-])+[[:xdigit:]]{2,}$/) { $key =~ s/[\:-]//g; return lc($key); } else { return qq("$key"); } } sub wlan_ng_needed { my ($module) = @_; $module =~ /^prism2_/; } #- 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 ($essid, $key, $device, $module) = @_; my $wlan_conf_file = "$::prefix/etc/wlan/wlan.conf"; my @wlan_devices = split(/ /, (cat_($wlan_conf_file) =~ /^WLAN_DEVICES="(.*)"/m)[0]); push @wlan_devices, $device unless member($device, @wlan_devices); #- enable device and make it use the choosen ESSID wlan_ng_update_vars($wlan_conf_file, { WLAN_DEVICES => qq("@wlan_devices"), "SSID_$device" => qq("$essid"), "ENABLE_$device" => "y" }); my $wlan_ssid_file = "$::prefix/etc/wlan/wlancfg-$essid"; #- copy default settings for this ESSID if config file does not exist -f $wlan_ssid_file or cp_f("$::prefix/etc/wlan/wlancfg-DEFAULT", $wlan_ssid_file); #- enable/disable encryption wlan_ng_update_vars($wlan_ssid_file, { (map { $_ => $key ? "true" : "false" } qw(lnxreq_hostWEPEncrypt lnxreq_hostWEPDecrypt dot11PrivacyInvoked dot11ExcludeUnencrypted)), AuthType => $key ? qq("sharedkey") : qq("opensystem"), if_($key, dot11WEPDefaultKeyID => 0, dot11WEPDefaultKey0 => qq("$key") ) }); #- hide settings for non-root users chmod 0600, $wlan_conf_file; chmod 0600, $wlan_ssid_file; #- apply settings on wlan interface require services; services::restart($module eq 'prism2_cs' ? 'pcmcia' : 'wlan'); } sub wpa_supplicant_get_driver { my ($module) = @_; $module =~ /^hostap_/ ? "hostap" : $module eq "prism54" ? "prism54" : $module =~ /^ath_/ ? "madwifi" : $module =~ /^at76c50|atmel_/ ? "atmel" : $module eq "ndiswrapper" ? "ndiswrapper" : $module =~ /^ipw2[12]00$/ ? "ipw" : "wext"; } sub wpa_supplicant_configure { my ($essid, $key) = @_; wpa_supplicant_add_network({ ssid => qq("$essid"), psk => convert_key_for_wpa_supplicant($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; } 1;