root/wifi-ltsp/trunk/parsehostapd/parsehostapd.py @ 441
50 | jredrejo | #!/usr/bin/python
|
|
44 | jredrejo | # -*- coding: utf-8 -*-
|
|
50 | jredrejo | # Project: wifi-ltsp
|
|
# Module: parsehostapd.py
|
|||
# Purpose: Parsea el fichero /etc/hostapd/hostapd.conf
|
|||
# Language: Python 2.5
|
|||
# Date: 26-Enero-2011.
|
|||
# Ver: 07-Feb-2011.
|
|||
# Author: Francisco Mora Sánchez
|
|||
# Copyright: 2011 - Francisco Mora Sánchez <adminies.maestrojuancalero@edu.juntaextremadura.net>
|
|||
#
|
|||
# wifi-ltsp 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 3 of the License, or
|
|||
# (at your option) any later version.
|
|||
# Script2 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 wifi-ltsp. If not, see <http://www.gnu.org/licenses/>.
|
|||
44 | jredrejo | ||
""" Módulo que contiene la función selectbestchannel()
|
|||
Función que escanea el espectro de canales de redes
|
|||
wifi y nos devuelve el canal más idóneo para ser utilizado en
|
|||
el lugar en que estamos.
|
|||
La función admite dos parámetros
|
|||
Utiliza la libreria pythonwifi y está basado en uno de los ejemplos
|
|||
incluidos en la libreria
|
|||
Debe ser ejecutado como root
|
|||
El algoritmo utilizado se basa en sumar las redes que existen en cada
|
|||
canal y a continuación calcular las sumas de los solapes de las redes
|
|||
centradas en canales, patrón 1-6-11, escogeremos el canal cuyo valor
|
|||
de las sumas sea menor.
|
|||
Los canales que se solapan en el patrón 1-6-11 son los siguientes:
|
|||
Canal Canales que se solapan
|
|||
1 1-5
|
|||
2 1-6
|
|||
3 1-7
|
|||
4 1-8
|
|||
5 1-9
|
|||
6 2-10
|
|||
7 3-11
|
|||
8 4-12
|
|||
9 5-13
|
|||
10 6-13
|
|||
11 7-13
|
|||
12 8-13
|
|||
13 9-13
|
|||
Francisco Mora Sánchez
|
|||
IES Maestro Juan Calero
|
|||
adminies.maestrojuancalero@edu.juntaextremadura.net
|
|||
"""
|
|||
import sys
|
|||
import os
|
|||
import socket
|
|||
#from pythonwifi.iwlibs import Wireless, getWNICnames
|
|||
import escanea
|
|||
def actualizadatosescaneo(datosescaneo, canal, bssid, essid, calidad, intensidad):
|
|||
""" Actualizamos diccionario con los datos recogidos del
|
|||
escaneado, comprobamos que no hemos insertado
|
|||
previamente la red, comprobando el bssid del AP
|
|||
"""
|
|||
if not datosescaneo.has_key(canal):
|
|||
#insertamos el canal inicializando los campos
|
|||
datosescaneo[canal] = [1, [[bssid,calidad,intensidad]], 0]
|
|||
else:
|
|||
#comprobemos que no existe ese bssid en el diccionario
|
|||
#listabssid = datosescaneo[canal][1]
|
|||
listabssid = [bssids[0] for bssids in datosescaneo[canal][1]]
|
|||
if not bssid in listabssid:
|
|||
#no está en la lista, añadimos y aumentamos el contador de redes
|
|||
datosescaneo[canal][0] = datosescaneo[canal][0] + 1
|
|||
datosescaneo[canal][1].append([bssid,calidad,intensidad])
|
|||
def procesadatosescaneo(datosescaneo):
|
|||
""" Sumamos las redes solapadas centradas en los canales, basándonos
|
|||
en el patrón 1-6-11
|
|||
"""
|
|||
adyacentes = {1:[1,2,3,4,5],2:[1,2,3,4,5,6],3:[1,2,3,4,5,6,7],4:[1,2,3,4,5,6,7,8],5:[1,2,3,4,5,6,7,8,9], \
|
|||
6:[2,3,4,5,6,7,8,9,10],7:[3,4,5,6,7,8,9,10,11],8:[4,5,6,7,8,9,10,11,12],9:[5,6,7,8,9,10,11,12,13], \
|
|||
10:[6,7,8,9,10,11,12,13],11:[7,8,9,10,11,12,13],12:[8,9,10,11,12,13],13:[9,10,11,12,13]}
|
|||
#Rellenamos canales faltantes
|
|||
for canal in range(1, 14):
|
|||
if not datosescaneo.has_key(canal):
|
|||
datosescaneo[canal] = [0, [], 0]
|
|||
#Sumemor las redes solapadas
|
|||
for canal in range(1, 14):
|
|||
for adyacente in adyacentes[canal]:
|
|||
datosescaneo[canal][2] = datosescaneo[canal][2] + datosescaneo[adyacente][0]
|
|||
def seleccionacanaloptimo(datosescaneo):
|
|||
""" Procesamos diccionario y retornamos el canal óptimo,
|
|||
aquel cuyo valor de numero de redes totales solapadas
|
|||
centradas es el mínimo
|
|||
"""
|
|||
#El mejor canal, es el menor valor de los solapes de las redes centradas en canales
|
|||
canaloptimo = 1
|
|||
valor = datosescaneo[1][2]
|
|||
for canal in range(1, 14):
|
|||
if datosescaneo[canal][2] < valor:
|
|||
canaloptimo = canal
|
|||
valor = datosescaneo[canal][2]
|
|||
return canaloptimo
|
|||
def selectbestchannel(verbose = False):
|
|||
""" Creamos diccionario para almacenar datos, la key principal es
|
|||
es el canal, y para cada canal hay una lista en
|
|||
la que se almacena el número de redes detectadas, sus BSSID junto
|
|||
a su potencia e intensidad, además se almacenará
|
|||
y el número de redes que se solapan con las redes centradas en canales
|
|||
según patrón 1-6-11.
|
|||
Controlaremos que no se dupliquen los canales cuando hay más de un interfaz wifi
|
|||
comparando los BSSID para este menester
|
|||
"""
|
|||
#Esta seria la estructura que obtendriamos de nuestro escaneado
|
|||
#{1:[3, [["MACAP1",70,-56], ["MACAP2",65,-61], ["MACAP3",60,-66]], 0],
|
|||
# 2:[2, [["MACAP4",75,-51], ["MACAP5",65,-61]], 0]
|
|||
# 3:[1, [["MACAP6",80,-45]], 0],
|
|||
# 4:[1, [["MACAP7",60,-66]], 0]}
|
|||
datosescaneo = {}
|
|||
if verbose:
|
|||
print "Escaneando redes WIFI..."
|
|||
index = 1
|
|||
for ifname in escanea.getWirelessInterfaces():
|
|||
if verbose:
|
|||
print " Escaneado de la interfaz %-8.16s" % (ifname, )
|
|||
otros_datos_escaneo = escanea.ObtieneRedes(ifname)
|
|||
if len(otros_datos_escaneo.keys()) == 0:
|
|||
if verbose:
|
|||
print "%-8.16s Escaneado sin resultados" % (ifname, )
|
|||
for bssid in otros_datos_escaneo.keys():
|
|||
if verbose:
|
|||
print " Red: %02d - Canal: %s BSSID: %s ESSID: %s Quality: %s Signal Strength: %s" % \
|
|||
(index, otros_datos_escaneo[bssid]['canal'], bssid, otros_datos_escaneo[bssid]['essid'], otros_datos_escaneo[bssid]['calidad'], otros_datos_escaneo[bssid]['intensidad'])
|
|||
#vamos a actualizar nuestro diccionario
|
|||
actualizadatosescaneo(datosescaneo, int(otros_datos_escaneo[bssid]['canal']), bssid, otros_datos_escaneo[bssid]['essid'], otros_datos_escaneo[bssid]['calidad'], otros_datos_escaneo[bssid]['intensidad'])
|
|||
index = index +1
|
|||
#para pruebas
|
|||
#datosescaneo = {1:[2, [["01",99,-99],["02",98,-98]], 0], 6:[3, [["03",97,-97],["04",96,-96],["05",95,-95]], 0], 11:[1, ["06",94,-94], 0]}
|
|||
procesadatosescaneo(datosescaneo)
|
|||
canaloptimo = seleccionacanaloptimo(datosescaneo)
|
|||
if verbose:
|
|||
print "\nTabla de datos obtenida:"
|
|||
print datosescaneo
|
|||
print "\n"
|
|||
print "El canal óptimo es el: ", canaloptimo
|
|||
return canaloptimo
|
|||
if __name__ == "__main__":
|
|||
""" Comprobaremos que se ha pasado la ruta al archivo hostapd.conf
|
|||
El archivo hostapd.conf debe contener la cadena 'canalseleccionado'
|
|||
que será reemplazada por la salida de la función selectchannelwifi().
|
|||
Además el SSID es el nombre de equipo menos la cadena '-pro', y
|
|||
la cadena a buscar en el archivo hostapd.conf es 'ssidseleccionado'.
|
|||
"""
|
|||
if len(sys.argv) == 1:
|
|||
print 'uso: ./parsehostapd.py /ruta/al/archivo/hostapd.conf'
|
|||
sys.exit(1)
|
|||
#Comprobemos la existencia del archivo
|
|||
hostapdconf = sys.argv[1]
|
|||
if not os.path.exists(hostapdconf):
|
|||
print "El archivo",hostapdconf,"no existe"
|
|||
exit(2)
|
|||
print "Procesando archivo",hostapdconf
|
|||
""" Aquí llamamos a la función desarrollada en este módulo
|
|||
para asignar el canal de transmisión óptimo,
|
|||
si ponemos True en el parámetro podremos ver las redes
|
|||
que se detectan...
|
|||
"""
|
|||
canaloptimo = selectbestchannel(True)
|
|||
ssid = socket.gethostname()
|
|||
pos = ssid.find(".")
|
|||
if pos > -1:
|
|||
ssid = ssid[:pos]
|
|||
pos = ssid.find("-pro")
|
|||
if pos > -1:
|
|||
ssid = ssid[:pos]
|
|||
try:
|
|||
#Abre el archivo para lectura de datos
|
|||
archivoLectura = open(hostapdconf,"r")
|
|||
lineas = archivoLectura.readlines()
|
|||
archivoLectura.close()
|
|||
except (RuntimeError, TypeError, NameError, IOError):
|
|||
print "Error en la ubicacion o nombre del archivo"
|
|||
exit()
|
|||
#Modifica la cadena del channel y ssid
|
|||
encontradoChannel = False
|
|||
encontradoSsid = False
|
|||
for numlinea in range(0, len(lineas)):
|
|||
linea = lineas[numlinea]
|
|||
#comprobamos si estamos en channel o en ssid
|
|||
if linea[:7] == "channel":
|
|||
encontradoChannel = True
|
|||
lineas[numlinea] = "channel="+str(canaloptimo)+"\n"
|
|||
if linea[:4] == "ssid":
|
|||
encontradoSsid = True
|
|||
lineas[numlinea] = "ssid="+ssid+"\n"
|
|||
if not encontradoChannel:
|
|||
lineas.append("channel="+str(canaloptimo)+"\n")
|
|||
if not encontradoSsid:
|
|||
lineas.append("ssid="+ssid+"\n")
|
|||
#Abre el archivo para escritura de datos
|
|||
archivoEscritura = open(hostapdconf,"w")
|
|||
archivoEscritura.writelines(lineas)
|
|||
archivoEscritura.close()
|
|||
print "El canal establecido es",canaloptimo
|
|||
print "El SSID establecido es",ssid
|
|||
print "Se ha procesado el archivo",hostapdconf
|