Proyecto

General

Perfil

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