#!/usr/bin/env python """API to map MAC addresses to hostnames""" from contextlib import contextmanager, closing from sqlite3 import connect from bottle import route, run, request from json import dumps import re import os __author__ = "Enrico Bacis" __email__ = "enrico.bacis@gmail.com" # Aggiunta di Emiliano Vavassori # Configuring default directories for the program dbdir = '/var/lib/mac2hostname' logdir = '/var/log/mac2hostname' piddir = '/var/run/mac2hostname' # Will create a PID file to be used with init.d script pid = os.getpid() op = open(piddir + '/service.pid', 'w') op.write("%s" % pid) op.close() @contextmanager def getcursor(db = dbdir + 'mac2hostname.db'): with connect(db) as connection: with closing(connection.cursor()) as cursor: yield cursor def init_tables(): with getcursor() as cursor: cursor.execute('CREATE TABLE IF NOT EXISTS client (id INT PRIMARY KEY,' 'hostname TEXT NOT NULL UNIQUE, mac TEXT UNIQUE)') cursor.execute('CREATE INDEX IF NOT EXISTS idxmac ON client(mac)') @route('/hosts') def hosts(): with getcursor() as cursor: return dumps([dict((meta[0], data) for meta, data in zip(cursor.description, row)) for row in cursor.execute('SELECT hostname, mac FROM client ORDER BY id')], indent=4) def normalizemac(mac): return ':'.join(x.zfill(2) for x in mac.split(':')).upper() def gethostname(mac, base=None): mac, base = normalizemac(mac), base or 'lab' with getcursor() as cursor: (newid,) = cursor.execute('SELECT COALESCE(MAX(id)+1, 1) FROM client').fetchone() cursor.execute('INSERT OR IGNORE INTO client VALUES (%s, "%s-%s", "%s")' % (newid, base, newid, mac)) (hostname,) = cursor.execute('SELECT hostname FROM client WHERE mac = "%s"' % mac) return hostname def getmac(ip): check_output(['ping', '-c1', '-t2', ip]) arp = check_output(['arp', '-n', ip]) return re.search(r'(([\da-fA-F]{1,2}\:){5}[\da-fA-F]{1,2})', arp).group(1) @route('/mac2hostname') def mac2hostname(): mac, base = request.query.mac, request.query.base if not mac: return 'Usage: GET /mac2hostname?mac=XX_XX_XX_XX_XX_XX[&base=YYY]' return gethostname(mac, base) @route('/whatsmyhostname') def whatsmyhostname(): ip = request.query.ip or request['REMOTE_ADDR'] return gethostname(getmac(ip), request.query.base) if __name__ == '__main__': init_tables() run(host='0.0.0.0', port=3000)