scripts/wifi/hotspot.py
bernat 1434139899 On peut pas redemarrer...
darcs-hash:20051118155445-d1718-9f0ef0173ca4f501e96cf280e1f1541e9a677bb2.gz
2005-11-18 16:54:45 +01:00

148 lines
4.7 KiB
Python
Executable file

#! /usr/bin/env python
# -*- encoding: iso-8859-15 -*-
# Gestion du portail captif :
# - lecture d'une socket pour les IP à ajouter
# - lecture du fichier de lease DHCP pour les expirer
import os
from popen2 import Popen4
import sys
import time
import re
from syslog import openlog, syslog, LOG_ERR, LOG_LOCAL4, LOG_INFO, LOG_LOCAL3, LOG_PERROR, LOG_PID, LOG_CRIT
from lease import Leases
from select import select
class Server:
"""Serveur (sur socket) gérant le hotspot"""
def __init__(self, socket):
"""Initialise le serveur.
Il écoutera sur le pipe nommé `socket'."""
# syslog
openlog("hotspot.py", LOG_PERROR | LOG_PID)
# Initialisation de la socket
self._dontclean = False
try:
os.unlink(socket)
except:
pass
os.mkfifo(socket, 0600)
os.chown(socket, 67, -1)
self.socket = file(socket, "a+")
def execute(self,cmd):
"""Exécute une commande.
Gère les erreurs par log dans syslog."""
p = Popen4(cmd)
p.tochild.close()
out = p.fromchild.read()
p.fromchild.close()
exit = os.WEXITSTATUS(p.wait())
if exit:
# Une erreur a eu lieu
syslog(LOG_ERR | LOG_LOCAL4,
"Error %d executing `%s' : %s" % (exit, cmd.strip(), out.strip()))
else:
return out
def add_ip(self,ip):
"""Ajout d'une IP au firewall"""
cmd = "pfctl -t clients_hotspot_autorises -Tadd %s" % ip
if self.execute(cmd):
syslog(LOG_INFO | LOG_LOCAL4, "Nouveau client hotspots: %s" % ip)
def del_ip(self,ip):
"""Retire une règle du firewall"""
cmd = "pfctl -t clients_hotspot_autorises -Tdelete %s" % ip
if self.execute(cmd):
syslog(LOG_INFO | LOG_LOCAL4, "Suppression du client: %s" % ip)
def list_ips(self):
"""Liste les IP actuellement dans le firewall"""
cmd = "pfctl -t clients_hotspot_autorises -Tshow"
ips = self.execute(cmd)
if not ips:
return []
return filter(lambda y: y.strip() != '',
map(lambda x: x.strip(), ips.split("\n")))
def prune_ips(self):
"""Vire les IP qui ne sont plus utilisées"""
l = Leases().leases
deleted = False
for ip in self.list_ips():
match = filter(lambda x: x.ip == ip, l)
if not match:
# Plus de bail du tout
self.del_ip(ip)
deleted = True
else:
# On vérifie si le bail n'a pas expiré depuis plus de une minute
if match[0].end < time.gmtime(time.time()-60):
self.del_ip(ip)
deleted=True
syslog(LOG_INFO | LOG_LOCAL3, "Clients hotspots: %s" % (", ".join(self.list_ips()) or "aucun"))
def daemonize(self):
"""Passe en arrière plan"""
# Fork
if os.fork() > 0:
self._dontclean = True
sys.exit(0)
# Bon répertoire
os.chdir("/")
# Masque indépendant de l'utilisateur
os.umask(022)
# Chef de file
os.setsid()
# Second fork pour avoir son groupe
if os.fork() > 0:
self._dontclean = True
sys.exit(0)
# Redirection des E/S
si = file('/dev/null', 'r')
so = file('/dev/null', 'a+')
se = file('/dev/null', 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
def start(self):
"""Boucle principale"""
syslog(LOG_INFO | LOG_LOCAL4, "Demarrage du demon hotspot")
s = self.socket.fileno()
while True:
# On attend du monde sur la socket
result = select([s],[],[],60)[0]
if result:
# On a quelqu'un, on lit une ligne
syslog(LOG_INFO | LOG_LOCAL4, "Nouvelle requete")
ip = self.socket.readline().strip()
syslog(LOG_INFO | LOG_LOCAL4, "Nouvelle requete pour l'IP : %s" % ip)
if re.match("^10\.231.*", ip):
self.add_ip(ip)
# Dans tous les cas, on vire les IP inutiles
self.prune_ips()
if __name__ == "__main__":
s = Server("/var/www/hotspot.socket")
s.daemonize()
while True:
try:
s.start()
except:
import traceback
from cStringIO import StringIO
ss = StringIO()
sys.stderr = ss
traceback.print_exc()
sys.stderr = sys.__stderr__
syslog(LOG_CRIT | LOG_LOCAL4, "Erreur importante :\n%s" % s.getvalue())
time.sleep(60) # Pour ne pas flooder...