#!/usr/bin/env python
#
# Scrive il file /opt/td-config/run/names/fnames 
#

import subprocess
import signal
import getopt
import re
import string
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *

global interface

def name_usage():
	print " "
	print "  NetBIOS/mDNS Name service usage:"
	print " "
	print "  -i <interface>    : The interface you want to sniff"
	print " "
	sys.exit()

	return

def name_service(pkt):
	typen = "UNKNOWN"
	source_mac = ""
	source_name = ""

	try:
		source_mac = pkt.getlayer(Ether).src
	except:
		return

	try:
                source_ip = pkt.getlayer(IP).src
        except:
                return

	if pkt.haslayer(NBTDatagram):
		typen = "NetBIOS"
		source_name = pkt.getlayer(NBTDatagram).SourceName

		for i in range(len(source_name) - 1, -1, -1):
			if source_name[i] == ' ':
				source_name = source_name[0:-1]

		if len(source_name) == 0:
			return

		name_service_resolve(typen, source_mac, source_ip, source_name)
	else:
		try:
			payload = DNS(pkt.getlayer(Raw).load)
		except:
			return

		name = ""
		ntype = 0 
		typen = "mDNS"

		try:
			if payload.haslayer(DNSRR) == False:
				return
		except:
			return

		dnsrr = payload.getlayer(DNSRR)

		if dnsrr == None:
			return

		counter = 0

		while True:
			try:
				name = dnsrr[counter].rrname
				ntype = dnsrr[counter].type
			except:
				return

			index = string.find(name, ".local")
			if index != -1:
				source_name = name[0:index]
			else:
				source_name = name

			if ntype != 1 or len(source_name) == 0:
				counter += 1
				continue

			name_service_resolve(typen, source_mac, source_ip, source_name)

			counter += 1

def name_service_resolve(typen, source_mac, source_ip, source_name):
	source_mac = source_mac.upper()
	source_name = source_name.upper()

	if string.find(source_name, "._TCP") != -1:
		return

	if string.find(source_name, "._UDP") != -1:
		return

	if string.find(source_name, ".ARPA") != -1:
		return

	if source_name == '.' or source_name == '.\n':
		return

	source_name_1 = source_name[0].upper()
        source_name_2 = source_name[1:].lower()
        source_name = source_name_1 + source_name_2

	f1 = open('fnames', 'r')
	f2 = open('fnames', 'a')
	state = 0

	for line in f1:
		space = string.find(line, " ")
		mac = line[0:space]
		space = space + 1
		line1 = line[space:len(line)]
		space1 = string.find(line1, " ")
		ip = line1[0:space1]
		space1 = space1 + 1
		name = line1[space1:len(line1) - 1]

		if mac == source_mac and ip == source_ip and name == source_name:
			state = 1
			break
		elif mac == source_mac and (ip != source_ip or name != source_name):
			state = 2
			break

	if state == 0:
		print "[     names][00000000] Added", typen, source_mac, source_ip, source_name 
		f2.write(source_mac + ' ' + source_ip + ' ' + source_name + '\n')
	elif state == 1:
		print "[     names][00000000] Present", typen, source_mac, source_ip, source_name
	elif state == 2:
		print "[     names][00000000] Changed", typen, source_mac, source_ip, source_name

		f1.close()
		f2.close()

		f1 = open('fnames', 'r')

		try:
			os.remove('fnames.tmp')
		except:
			pass

		f2 = open('fnames.tmp', 'w+')

		for line in f1:
			space = string.find(line, " ")
			mac = line[0:space]

			if mac == source_mac:
				f2.write(source_mac + ' ' + source_ip + ' ' + source_name + '\n')
			else:
				f2.write(line)

	f1.close()
	f2.close()

	if state == 2:
		os.rename('fnames.tmp', 'fnames')

	return

def signal_handler(signum, frame):
	global interface

	print "[     names][00000000] Signal caught."
	print "[     names][00000000] Sniffing on", interface, "off"
	print "[     names][00000000]", interface, "promiscue mode off"
	subprocess.call(['ifconfig', interface, '-promisc'])

	sys.exit()

	return

def main():
	global interface

	try:
		opts, args = getopt.getopt(sys.argv[1:],"i:")
	except:
		name_usage()
		sys.exit(1)

	interface = None

	for o, a in opts:
		if o == '-i':
			interface = a

	if args or not interface:
		name_usage()
		sys.exit(1)

	try:
		os.makedirs('/opt/td-config/run/names/')
	except:
		pass
	
	os.chdir('/opt/td-config/run/names/')
	
	try:
		os.remove('fnames')
	except:
		pass

	f = open('fnames', 'w')
	f.close()

	signal.signal(signal.SIGINT, signal_handler)
	signal.signal(signal.SIGTERM, signal_handler)

	print "[     names][00000000]", interface, "promiscue mode on"
	subprocess.call(["ifconfig", interface, 'promisc'])

	print "[     names][00000000] Sniffing on", interface, "on"

	try:
	    sniff(iface=interface, filter="port 138 or port 5353", store=0, prn=name_service)
	except:
	    return

	return

if __name__ == "__main__":
	main()
