127 lines
4.1 KiB
Python
Executable file
127 lines
4.1 KiB
Python
Executable file
#!/usr/bin/env python
|
|
# -*- coding: utf8 -*-
|
|
#
|
|
#
|
|
# PEB - 01/04/2012 -> now()
|
|
#
|
|
# Ce script est placé sous la licence libre par défaut
|
|
# utilisée au Crans. Ayant la flemme de copier/coller
|
|
# celle-ci, démerdez-vous avec un des responsables de
|
|
# l'association pour les fioritures.
|
|
|
|
import os
|
|
import sys
|
|
import sys
|
|
import re
|
|
import socket
|
|
|
|
from commands import getstatusoutput
|
|
|
|
# 1 avril 2012 - PEB :
|
|
# nécessite apparemment que l'objet conn soit bien créé lors de l'exec
|
|
# de annuaires_pg, il faut être root (ou dans je ne sais quel groupe)
|
|
# pour que l'authentification de l'user crans avec psycopg2 se fasse
|
|
# (plante lamentablement quand j'essaye avec mon compte sur vo, sous
|
|
# ipython. Mais si je sudo ipython, ça marche...
|
|
|
|
def host_exists(hostname):
|
|
"""Vérifie si hostname résout bien, sinon retourne false"""
|
|
try:
|
|
socket.gethostbyname(hostname)
|
|
except socket.gaierror:
|
|
return False
|
|
return True
|
|
|
|
def liste_chambres_macs(switch, annuaire):
|
|
u'''
|
|
Fonction générant un dictionnaire (macs) contenant pour chaque prise une
|
|
liste des macs qui y sont actives.
|
|
Reçoit annuaires_pg en second argument, pour éviter l'ouverture de
|
|
multiples connexions sql pour rien.
|
|
'''
|
|
liste_bats = ['a', 'b', 'c', 'g', 'h', 'i', 'j', 'm', 'p']
|
|
|
|
split = switch.split(".")[0].split('-')
|
|
bat, num_switch = split[0][-1], int(split[1][0])
|
|
if bat not in liste_bats:
|
|
return {}
|
|
if not host_exists(switch):
|
|
switch = switch.replace('adm.crans.org', 'crans.org')
|
|
if not host_exists(switch):
|
|
return {}
|
|
data = walk(switch, 'STATISTICS-MIB::hpSwitchPortFdbAddress')
|
|
|
|
liste_chbres = []
|
|
macs = {}
|
|
if data:
|
|
for port in data:
|
|
if port == '':
|
|
continue
|
|
else:
|
|
mac = data[port]
|
|
uplink = annuaire.uplink_prises[bat]
|
|
prise = num_switch * 100 + port
|
|
if prise in uplink:
|
|
continue
|
|
|
|
result = annuaire.reverse(bat, prise)
|
|
if result:
|
|
chbre = bat+result[0]
|
|
if chbre in liste_chbres:
|
|
macs[chbre].extend(mac)
|
|
else:
|
|
macs[chbre] = []
|
|
macs[chbre].extend(mac)
|
|
liste_chbres.append(chbre)
|
|
del chbre
|
|
else:
|
|
# On droppe, c'est des bornes wifi ou autres.
|
|
pass
|
|
else:
|
|
print "Pas de données pour %s" % (switch)
|
|
return macs
|
|
|
|
def walk(host, oid):
|
|
u'''
|
|
Hack sale remplaçant la fonction walk contenue dans hptools, qui
|
|
splitte suivant des espaces, ce qui engendre des failles.
|
|
Ici, snmpwalk -Ox (au lieu de -Oq) fait qu'on récupère bien des macs,
|
|
et on splitte suivant le keyword Hex-STRING, qui n'est pas redondant, lui.
|
|
'''
|
|
received = __exec('snmpwalk -Ox -v 1 -c public %s %s' % (host, oid)).split('\n')
|
|
result = {}
|
|
for ligne in received:
|
|
try:
|
|
pport, pmac = ligne.split('Hex-STRING: ')
|
|
|
|
port = int(pport.replace('STATISTICS-MIB::hpSwitchPortFdbAddress.', '').split('.')[0])
|
|
mac = pmac.replace(' ', '').lower().replace('"', '')
|
|
if not re.match('([0-9a-f]{2}){6}', mac):
|
|
mac = mac.encode('hex').lower()
|
|
mac = "%s:%s:%s:%s:%s:%s" % (mac[0:2], mac[2:4], mac[4:6], mac[6:8], mac[8:10], mac[10:12])
|
|
if not result.has_key(port):
|
|
result[port] = [mac]
|
|
else:
|
|
result[port].append(mac)
|
|
except:
|
|
print "Ligne moisie : %s de l'hôte : %s" % (ligne, host)
|
|
return result
|
|
|
|
|
|
def __exec(cmd):
|
|
u'''
|
|
Hack sale pour pas loader inutilement hptools.py
|
|
Exécute une commande et retourne son status et son output.
|
|
'''
|
|
status, response = getstatusoutput(cmd)
|
|
if status:
|
|
response = response.replace('snmpget: ','')
|
|
print 'Erreur : '+response+' : '+cmd
|
|
return response
|
|
|
|
if __name__ == '__main__':
|
|
switchs = sys.argv[1:]
|
|
for switch in switchs:
|
|
macs = liste_chambres_macs(switch)
|
|
|
|
print macs
|