from scapy.all import *
import datetime
import os
import binascii
import yaml
import sqlite3
from datetime import datetime
import active_scan
import protocol_actions
import threading
import requests
import json_operations as jo
from helpers.Packet_Analyzer import Packet_Analyzer

try:
	yamlfile=open("config.yaml")
	data = yaml.load(yamlfile, Loader=yaml.FullLoader)
	server_ip=data["configuration"]["unifytwin_server_ip_address"]
	plant=data["configuration"]["edge_device_location"]
	balacklist_ips=data["configuration"]["blacklist_ip"]
	blacklist_dns=data["configuration"]["blacklist_dns"]
	configured_threads=data["configuration"]["threads"]
	interfaces=data["configuration"]["interfaces"]
	null_loopback=data["configuration"]["null_loopback"]
except Exception as e:
	server_ip=""
	plant="Unknown Location"
	balacklist_ips=['46.4.105.116','172.67.214.157','3.6.115.64','104.21.53.154']
	blacklist_dns=['webhook.site.','hpd.gasmi.net.','dd01-14-98-12-178.in.ngrok.io.']
	configured_threads=10
	interfaces='eth0'
	null_loopback=False


from sys import platform
if platform == "linux" or platform == "linux2":
    clearing='clear'
elif platform == "darwin":
    clearing='clear'
elif platform == "win32":
    clearing='cls'


def convert_text(pkt):
	inhex=binascii.hexlify(bytes(pkt))
	if(null_loopback):
		inhex=b'0000000000000000000000000800'+inhex[8:] if inhex[:2]==b'02' else b'00000000000000000000000086DD'+inhex[8:]
	try:
		pa = Packet_Analyzer()
		protocols=pa.identify_protocol(inhex)
		ip=pa.get_ip(inhex)
		if(ip):
			mac=pa.get_mac(inhex)
			check_exist=jo.check_asset_exists(ip)
			if(not check_exist):
				dev_type,vendor,firmware,model=protocol_actions.analyse_protocol(protocols,pkt)
				operating_sys=pa.get_os(inhex)
				jo.insert_asset(ip,datetime.now().strftime("%d-%m-%y %H:%M:%S"),dev_type,str(protocols),mac,vendor,firmware,model,operating_sys,plant)
			else:
				prev_protocols=jo.get_existing_protocols(ip)
				extra_proto=set(protocols.split(':'))-set(prev_protocols.split(':'))
				if(extra_proto):
					dev_type,vendor,firmware,model=protocol_actions.update_protocol(protocols,pkt)
					prev_protocols=prev_protocols+':'+str(extra_proto).replace(", ",":").replace("{","").replace("}","").replace("'","")
					if(dev_type!="Unknown"):
						jo.update_asset(ip,prev_protocols,datetime.now().strftime("%d-%m-%y %H:%M:%S"),dev_type,vendor,firmware,model)
					else:
						jo.update_last_activity_and_protocols(ip,prev_protocols,datetime.now().strftime("%d-%m-%y %H:%M:%S"))
				else:
					jo.update_last_activity(ip,datetime.now().strftime("%d-%m-%y %H:%M:%S"))
	except sqlite3.OperationalError as e:
		exc_type, exc_obj, exc_tb = sys.exc_info()
		fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
		print(exc_type, fname, exc_tb.tb_lineno,e)
		pass

	except Exception as e:
		exc_type, exc_obj, exc_tb = sys.exc_info()
		fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
		print(exc_type, fname, exc_tb.tb_lineno,e)
		pass

def gasmi_api(pkt):
	if(pkt.haslayer(IP)):
		if(pkt[IP].src not in balacklist_ips and pkt[IP].dst not in balacklist_ips):
			if(pkt.haslayer(DNS)):
				try:
					if(pkt[DNS]["DNS Question Record"].qname.decode() not in blacklist_dns):
						convert_text(pkt)
				except:
					pass
			else:
				convert_text(pkt)
	else:
		convert_text(pkt)

def packet_transmit(pkt):
	inhex=binascii.hexlify(bytes(pkt))
	requests.get(server_ip,data=inhex)

def network_sniffing_local_storage(pkt):
	if(threading.active_count()<configured_threads):
		ti=threading.Thread(target=gasmi_api, args=pkt,)
		ti.start()

def start_sniff(iface=interfaces):
	act_scn=active_scan.Active_Scan()
	ti = threading.Thread(target=act_scn.scan_for_assets)
	ti.start()
	sniff(iface=iface,prn=network_sniffing_local_storage)

if __name__=="__main__":
		start_sniff()