SystemPlugins/WirelessLan: improve wireless device/module detection.
[enigma2.git] / lib / python / Plugins / SystemPlugins / WirelessLan / Wlan.py
1 from Components.config import config, ConfigYesNo, NoSave, ConfigSubsection, ConfigText, ConfigSelection, ConfigPassword
2 from Components.Console import Console
3
4 from os import system, path as os_path
5 from string import maketrans, strip
6 import sys
7 import types
8 from re import compile as re_compile, search as re_search
9 from pythonwifi.iwlibs import getNICnames, Wireless, Iwfreq, getWNICnames
10 from pythonwifi import flags as wififlags
11
12 list = []
13 list.append("WEP")
14 list.append("WPA")
15 list.append("WPA2")
16 list.append("WPA/WPA2")
17
18 weplist = []
19 weplist.append("ASCII")
20 weplist.append("HEX")
21
22 config.plugins.wlan = ConfigSubsection()
23 config.plugins.wlan.essid = NoSave(ConfigText(default = "home", fixed_size = False))
24 config.plugins.wlan.hiddenessid = NoSave(ConfigText(default = "home", fixed_size = False))
25
26 config.plugins.wlan.encryption = ConfigSubsection()
27 config.plugins.wlan.encryption.enabled = NoSave(ConfigYesNo(default = True))
28 config.plugins.wlan.encryption.type = NoSave(ConfigSelection(list, default = "WPA/WPA2"))
29 config.plugins.wlan.encryption.wepkeytype = NoSave(ConfigSelection(weplist, default = "ASCII"))
30 config.plugins.wlan.encryption.psk = NoSave(ConfigPassword(default = "mysecurewlan", fixed_size = False))
31
32 class Wlan:
33         def __init__(self, iface):
34                 a = ''; b = ''
35                 for i in range(0, 255):
36                         a = a + chr(i)
37                         if i < 32 or i > 127:
38                                 b = b + ' '
39                         else:
40                                 b = b + chr(i)
41                 
42                 self.iface = iface
43                 self.wlaniface = {}
44                 self.WlanConsole = Console()
45                 self.asciitrans = maketrans(a, b)
46
47         def stopWlanConsole(self):
48                 if self.WlanConsole is not None:
49                         print "[Wlan] killing self.WlanConsole"
50                         self.WlanConsole.killAll()
51                         self.WlanConsole = None
52                         del self.WlanConsole
53                         
54         def getDataForInterface(self, callback = None):
55                 if len(self.WlanConsole.appContainers) == 0:
56                         self.WlanConsole = Console()
57                         cmd = "iwconfig " + self.iface
58                         self.WlanConsole.ePopen(cmd, self.iwconfigFinished, callback)
59
60         def iwconfigFinished(self, result, retval, extra_args):
61                 callback = extra_args
62                 data = { 'essid': False, 'frequency': False, 'acesspoint': False, 'bitrate': False, 'encryption': False, 'quality': False, 'signal': False }
63                 
64                 for line in result.splitlines():
65                         line = line.strip()
66                         if "ESSID" in line:
67                                 if "off/any" in line:
68                                         ssid = _("No Connection")
69                                 else:
70                                         if "Nickname" in line:
71                                                 tmpssid=(line[line.index('ESSID')+7:line.index('"  Nickname')])
72                                                 if tmpssid == '':
73                                                         ssid = _("Hidden networkname")
74                                                 elif tmpssid ==' ':
75                                                         ssid = _("Hidden networkname")
76                                                 else:
77                                                         ssid = tmpssid
78                                         else:
79                                                 tmpssid=(line[line.index('ESSID')+7:len(line)-1])
80                                                 if tmpssid == '':
81                                                         ssid = _("Hidden networkname")
82                                                 elif tmpssid ==' ':
83                                                         ssid = _("Hidden networkname")
84                                                 else:
85                                                         ssid = tmpssid                                          
86                                 if ssid is not None:
87                                         data['essid'] = ssid
88                         if 'Frequency' in line:
89                                 frequency = line[line.index('Frequency')+10 :line.index(' GHz')]
90                                 if frequency is not None:
91                                         data['frequency'] = frequency
92                         if "Access Point" in line:
93                                 ap=line[line.index('Access Point')+14:len(line)-1]
94                                 if ap is not None:
95                                         data['acesspoint'] = ap
96                         if "Bit Rate" in line:
97                                 br = line[line.index('Bit Rate')+9 :line.index(' Mb/s')]
98                                 if br is not None:
99                                         data['bitrate'] = br
100                         if 'Encryption key' in line:
101                                 if ":off" in line:
102                                     enc = _("Disabled")
103                                 else:
104                                     enc = line[line.index('Encryption key')+15 :line.index('   Security')]
105                                 if enc is not None:
106                                         data['encryption'] = _("Enabled")
107                         if 'Quality' in line:
108                                 if "/100" in line:
109                                         qual = line[line.index('Quality')+8:line.index('/100')]
110                                 else:
111                                         qual = line[line.index('Quality')+8:line.index('Sig')]
112                                 if qual is not None:
113                                         data['quality'] = qual
114                         if 'Signal level' in line:
115                                 signal = line[line.index('Signal level')+13 :line.index(' dBm')]
116                                 if signal is not None:
117                                         data['signal'] = signal
118
119                 self.wlaniface[self.iface] = data
120                 
121                 if len(self.WlanConsole.appContainers) == 0:
122                         print "[Wlan.py] self.wlaniface after loading:", self.wlaniface
123                         if callback is not None:
124                                 callback(True,self.wlaniface)
125
126         def getAdapterAttribute(self, attribute):
127                 if self.wlaniface.has_key(self.iface):
128                         print "[Wlan.py] self.wlaniface.has_key",self.iface
129                         if self.wlaniface[self.iface].has_key(attribute):
130                                 return self.wlaniface[self.iface][attribute]
131                 return None
132                 
133         def asciify(self, str):
134                 return str.translate(self.asciitrans)
135         
136         def getWirelessInterfaces(self):
137                 return getWNICnames()
138
139         def getNetworkList(self):
140                 system("ifconfig "+self.iface+" up")
141                 ifobj = Wireless(self.iface) # a Wireless NIC Object
142                 #Association mappings
143                 #stats, quality, discard, missed_beacon = ifobj.getStatistics()
144                 #snr = quality.signallevel - quality.noiselevel
145                 try:
146                         scanresults = ifobj.scan()
147                 except:
148                         scanresults = None
149                         print "[Wlan.py] No Wireless Networks could be found"
150                 
151                 if scanresults is not None:
152                         aps = {}
153                         (num_channels, frequencies) = ifobj.getChannelInfo()
154                         index = 1
155                         for result in scanresults:
156                                 bssid = result.bssid
157
158                                 if result.encode.flags & wififlags.IW_ENCODE_DISABLED > 0:
159                                         encryption = False
160                                 elif result.encode.flags & wififlags.IW_ENCODE_NOKEY > 0:
161                                         encryption = True
162                                 else:
163                                         encryption = None
164                                 
165                                 signal = str(result.quality.siglevel-0x100) + " dBm"
166                                 quality = "%s/%s" % (result.quality.quality,ifobj.getQualityMax().quality)
167                                 
168                                 extra = []
169                                 for element in result.custom:
170                                         element = element.encode()
171                                         extra.append( strip(self.asciify(element)) )
172                                 for element in extra:
173                                         print element
174                                         if 'SignalStrength' in element:
175                                                 signal = element[element.index('SignalStrength')+15:element.index(',L')]                                        
176                                         if 'LinkQuality' in element:
177                                                 quality = element[element.index('LinkQuality')+12:len(element)]                         
178
179                                 aps[bssid] = {
180                                         'active' : True,
181                                         'bssid': result.bssid,
182                                         'channel': frequencies.index(ifobj._formatFrequency(result.frequency.getFrequency())) + 1,
183                                         'encrypted': encryption,
184                                         'essid': strip(self.asciify(result.essid)),
185                                         'iface': self.iface,
186                                         'maxrate' : ifobj._formatBitrate(result.rate[-1][-1]),
187                                         'noise' : '',#result.quality.nlevel-0x100,
188                                         'quality' : str(quality),
189                                         'signal' : str(signal),
190                                         'custom' : extra,
191                                 }
192                                 #print "GOT APS ENTRY:",aps[bssid]
193                                 index = index + 1
194                         return aps
195                 
196         def getStatus(self):
197                 ifobj = Wireless(self.iface)
198                 fq = Iwfreq()
199                 try:
200                         self.channel = str(fq.getChannel(str(ifobj.getFrequency()[0:-3])))
201                 except:
202                         self.channel = 0
203                 status = {
204                                   'BSSID': str(ifobj.getAPaddr()), #ifobj.getStatistics()
205                                   'ESSID': str(ifobj.getEssid()),
206                                   'quality': "%s/%s" % (ifobj.getStatistics()[1].quality,ifobj.getQualityMax().quality),
207                                   'signal': str(ifobj.getStatistics()[1].siglevel-0x100) + " dBm",
208                                   'bitrate': str(ifobj.getBitrate()),
209                                   'channel': str(self.channel),
210                                   #'channel': str(fq.getChannel(str(ifobj.getFrequency()[0:-3]))),
211                 }
212                 for (key, item) in status.items():
213                         if item is "None" or item is "":
214                                         status[key] = _("N/A")
215                 return status
216
217
218 class wpaSupplicant:
219         def __init__(self, iface):
220                 self.iface = iface
221                 pass
222                 
223         def writeConfig(self):  
224                         essid = config.plugins.wlan.essid.value
225                         hiddenessid = config.plugins.wlan.hiddenessid.value
226                         encrypted = config.plugins.wlan.encryption.enabled.value
227                         encryption = config.plugins.wlan.encryption.type.value
228                         wepkeytype = config.plugins.wlan.encryption.wepkeytype.value
229                         psk = config.plugins.wlan.encryption.psk.value
230                         fp = file('/etc/' + self.iface + '_wpa_supplicant.conf', 'w')
231                         fp.write('#WPA Supplicant Configuration by enigma2\n')
232                         fp.write('ctrl_interface=/var/run/wpa_supplicant\n')
233                         fp.write('eapol_version=1\n')
234                         fp.write('fast_reauth=1\n')     
235                         if essid == 'hidden...':
236                                 fp.write('ap_scan=2\n')
237                         else:
238                                 fp.write('ap_scan=1\n')
239                         fp.write('network={\n')
240                         if essid == 'hidden...':
241                                 fp.write('\tssid="'+hiddenessid+'"\n')
242                         else:
243                                 fp.write('\tssid="'+essid+'"\n')
244                         fp.write('\tscan_ssid=0\n')                     
245                         if encrypted:
246                                 if encryption in ('WPA', 'WPA2', 'WPA/WPA2'):
247                                         fp.write('\tkey_mgmt=WPA-PSK\n')
248                 
249                                         if encryption == 'WPA':
250                                                 fp.write('\tproto=WPA\n')
251                                                 fp.write('\tpairwise=TKIP\n')
252                                                 fp.write('\tgroup=TKIP\n')
253                                         elif encryption == 'WPA2':
254                                                 fp.write('\tproto=RSN\n')
255                                                 fp.write('\tpairwise=CCMP\n')
256                                                 fp.write('\tgroup=CCMP\n')
257                                         else:
258                                                 fp.write('\tproto=WPA RSN\n')
259                                                 fp.write('\tpairwise=CCMP TKIP\n')
260                                                 fp.write('\tgroup=CCMP TKIP\n')
261                                         fp.write('\tpsk="'+psk+'"\n')
262                                 elif encryption == 'WEP':
263                                         fp.write('\tkey_mgmt=NONE\n')
264                                         if wepkeytype == 'ASCII':
265                                                 fp.write('\twep_key0="'+psk+'"\n')
266                                         else:
267                                                 fp.write('\twep_key0='+psk+'\n')
268                         else:
269                                 fp.write('\tkey_mgmt=NONE\n')                   
270                         fp.write('}')
271                         fp.write('\n')
272                         fp.close()
273                         system('cat /etc/' + self.iface + '_wpa_supplicant.conf')
274                 
275         def loadConfig(self):
276                 configfile = '/etc/wpa_supplicant.conf'
277                 if os_path.isfile('/etc/' + self.iface + '_wpa_supplicant.conf'):
278                         configfile = '/etc/' + self.iface + '_wpa_supplicant.conf'
279                 print "[wpaSupplicant] using configfile:",configfile
280                 try:
281                         #parse the wpasupplicant configfile
282                         fp = file(configfile, 'r')
283                         supplicant = fp.readlines()
284                         fp.close()
285                         ap_scan = False
286                         essid = None
287
288                         for s in supplicant:
289                                 split = s.strip().split('=',1)
290                                 if split[0] == 'ap_scan':
291                                         print "[Wlan.py] Got Hidden SSID Scan  Value "+split[1]
292                                         if split[1] == '2':
293                                                 ap_scan = True
294                                         else:
295                                                 ap_scan = False
296                                                 
297                                 elif split[0] == 'ssid':
298                                         print "[Wlan.py] Got SSID "+split[1][1:-1]
299                                         essid = split[1][1:-1]
300                                         
301                                 elif split[0] == 'proto':
302                                         config.plugins.wlan.encryption.enabled.value = True
303                                         if split[1] == 'WPA' :
304                                                 mode = 'WPA'
305                                         if split[1] == 'RSN':
306                                                 mode = 'WPA2'
307                                         if split[1] in ('WPA RSN', 'WPA WPA2'):
308                                                 mode = 'WPA/WPA2'
309                                         config.plugins.wlan.encryption.type.value = mode
310                                         print "[Wlan.py] Got Encryption: "+mode
311                                         
312                                 elif split[0] == 'wep_key0':
313                                         config.plugins.wlan.encryption.enabled.value = True
314                                         config.plugins.wlan.encryption.type.value = 'WEP'
315                                         if split[1].startswith('"') and split[1].endswith('"'):
316                                                 config.plugins.wlan.encryption.wepkeytype.value = 'ASCII'
317                                                 config.plugins.wlan.encryption.psk.value = split[1][1:-1]
318                                         else:
319                                                 config.plugins.wlan.encryption.wepkeytype.value = 'HEX'
320                                                 config.plugins.wlan.encryption.psk.value = split[1]                                             
321                                         
322                                 elif split[0] == 'psk':
323                                         config.plugins.wlan.encryption.psk.value = split[1][1:-1]
324                                 else:
325                                         pass
326                                 
327                         if ap_scan is True:
328                                 config.plugins.wlan.hiddenessid.value = essid
329                                 config.plugins.wlan.essid.value = 'hidden...'
330                         else:
331                                 config.plugins.wlan.hiddenessid.value = essid
332                                 config.plugins.wlan.essid.value = essid
333                         wsconfig = {
334                                         'hiddenessid': config.plugins.wlan.hiddenessid.value,
335                                         'ssid': config.plugins.wlan.essid.value,
336                                         'encryption': config.plugins.wlan.encryption.enabled.value,
337                                         'encryption_type': config.plugins.wlan.encryption.type.value,
338                                         'encryption_wepkeytype': config.plugins.wlan.encryption.wepkeytype.value,
339                                         'key': config.plugins.wlan.encryption.psk.value,
340                                 }
341                 
342                         for (key, item) in wsconfig.items():
343                                 if item is "None" or item is "":
344                                         if key == 'hiddenessid':
345                                                 wsconfig['hiddenessid'] = "home"
346                                         if key == 'ssid':
347                                                 wsconfig['ssid'] = "home"
348                                         if key == 'encryption':
349                                                 wsconfig['encryption'] = True                           
350                                         if key == 'encryption':
351                                                 wsconfig['encryption_type'] = "WPA/WPA2"
352                                         if key == 'encryption':
353                                                 wsconfig['encryption_wepkeytype'] = "ASCII"
354                                         if key == 'encryption':
355                                                 wsconfig['key'] = "mysecurewlan"
356                 except:
357                         print "[Wlan.py] Error parsing ",configfile
358                         wsconfig = {
359                                         'hiddenessid': "home",
360                                         'ssid': "home",
361                                         'encryption': True,
362                                         'encryption_type': "WPA/WPA2",
363                                         'encryption_wepkeytype': "ASCII",
364                                         'key': "mysecurewlan",
365                                 }
366                 print "[Wlan.py] WS-CONFIG-->",wsconfig
367                 return wsconfig
368
369
370 class Status:
371         def __init__(self):
372                 self.wlaniface = {}
373                 self.backupwlaniface = {}
374                 self.WlanConsole = Console()
375
376         def stopWlanConsole(self):
377                 if self.WlanConsole is not None:
378                         print "[iStatus] killing self.WlanConsole"
379                         self.WlanConsole.killAll()
380                         self.WlanConsole = None
381                         
382         def getDataForInterface(self, iface, callback = None):
383                 self.WlanConsole = Console()
384                 cmd = "iwconfig " + iface
385                 self.WlanConsole.ePopen(cmd, self.iwconfigFinished, [iface, callback])
386
387         def iwconfigFinished(self, result, retval, extra_args):
388                 (iface, callback) = extra_args
389                 data = { 'essid': False, 'frequency': False, 'acesspoint': False, 'bitrate': False, 'encryption': False, 'quality': False, 'signal': False }
390                 for line in result.splitlines():
391                         line = line.strip()
392                         if "ESSID" in line:
393                                 if "off/any" in line:
394                                         ssid = _("No Connection")
395                                 else:
396                                         if "Nickname" in line:
397                                                 tmpssid=(line[line.index('ESSID')+7:line.index('"  Nickname')])
398                                                 if tmpssid == '':
399                                                         ssid = _("Hidden networkname")
400                                                 elif tmpssid ==' ':
401                                                         ssid = _("Hidden networkname")
402                                                 else:
403                                                         ssid = tmpssid
404                                         else:
405                                                 tmpssid=(line[line.index('ESSID')+7:len(line)-1])
406                                                 if tmpssid == '':
407                                                         ssid = _("Hidden networkname")
408                                                 elif tmpssid ==' ':
409                                                         ssid = _("Hidden networkname")
410                                                 else:
411                                                         ssid = tmpssid                                          
412                                 if ssid is not None:
413                                         data['essid'] = ssid
414                         if 'Frequency' in line:
415                                 frequency = line[line.index('Frequency')+10 :line.index(' GHz')]
416                                 if frequency is not None:
417                                         data['frequency'] = frequency
418                         if "Access Point" in line:
419                                 ap=line[line.index('Access Point')+14:len(line)]
420                                 if ap is not None:
421                                         data['acesspoint'] = ap
422                                         if ap == "Not-Associated":
423                                                 data['essid'] = _("No Connection")
424                         if "Bit Rate" in line:
425                                 if "kb" in line:
426                                         br = line[line.index('Bit Rate')+9 :line.index(' kb/s')]
427                                         if br == '0':
428                                                 br = _("Unsupported")
429                                         else:
430                                                 br += " Mb/s"
431                                 else:
432                                         br = line[line.index('Bit Rate')+9 :line.index(' Mb/s')] + " Mb/s"
433                                 if br is not None:
434                                         data['bitrate'] = br
435                         if 'Encryption key' in line:
436                                 if ":off" in line:
437                                         if data['acesspoint'] is not "Not-Associated":
438                                                 enc = _("Unsupported")
439                                         else:
440                                                 enc = _("Disabled")
441                                 elif "Security" in line:
442                                         enc = line[line.index('Encryption key')+15 :line.index('   Security')]
443                                         if enc is not None:
444                                                 enc = _("Enabled")
445                                 else:
446                                         enc = line[line.index('Encryption key')+15 :len(line)]
447                                         if enc is not None:
448                                                 enc = _("Enabled")                                      
449                                 if enc is not None:
450                                         data['encryption'] = enc
451                         if 'Quality' in line:
452                                 if "/100" in line:
453                                         qual = line[line.index('Quality')+8:line.index('  Signal')]
454                                 else:
455                                         qual = line[line.index('Quality')+8:line.index('Sig')]
456                                 if qual is not None:
457                                         data['quality'] = qual
458                         if 'Signal level' in line:
459                                 if "dBm" in line:
460                                         signal = line[line.index('Signal level')+13 :line.index(' dBm')]
461                                         signal += " dBm"
462                                 elif "/100" in line:
463                                         if "Noise" in line:
464                                                 signal = line[line.index('Signal level')+13:line.index('  Noise')]
465                                         else:
466                                                 signal = line[line.index('Signal level')+13:len(line)]
467                                 else:
468                                         if "Noise" in line:
469                                                 signal = line[line.index('Signal level')+13:line.index('  Noise')]
470                                         else:
471                                                 signal = line[line.index('Signal level')+13:len(line)]                                          
472                                 if signal is not None:
473                                         data['signal'] = signal
474
475                 self.wlaniface[iface] = data
476                 self.backupwlaniface = self.wlaniface
477                 
478                 if self.WlanConsole is not None:
479                         if len(self.WlanConsole.appContainers) == 0:
480                                 print "[Wlan.py] self.wlaniface after loading:", self.wlaniface
481                                 if callback is not None:
482                                         callback(True,self.wlaniface)
483
484         def getAdapterAttribute(self, iface, attribute):
485                 self.iface = iface
486                 if self.wlaniface.has_key(self.iface):
487                         if self.wlaniface[self.iface].has_key(attribute):
488                                 return self.wlaniface[self.iface][attribute]
489                 return None
490         
491 iStatus = Status()