diff --git a/network_devices.py b/network_devices.py index 40a2968..9ce4a03 100644 --- a/network_devices.py +++ b/network_devices.py @@ -2,25 +2,32 @@ from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtWidgets import * from scapy.all import * -from scapy.layers.l2 import ARP, Ether +from network_monitor import InterfacePick class NetworkDevices(QWidget): def __init__(self): super().__init__() + self.networkIP = '' self.layout = QGridLayout() self.header = QLabel("Connected hosts on the network:") + self.interfbtn = QPushButton() + self.interfbtn.setFixedSize(300, 40) + self.interfbtn.setText('[Select Network]') + self.interfbtn.clicked.connect(self.networkInterface) + self.refreshbtn = QPushButton() self.refreshbtn.setFixedSize(350, 40) self.refreshbtn.setText('Refresh Status') - self.refreshbtn.clicked.connect(self.refreshStatus) + self.refreshbtn.clicked.connect(self.getConnectedDevices) self._createTable() self.layout.addWidget(self.header, 0, 0) - self.layout.addWidget(self.refreshbtn, 0, 1) - self.layout.addWidget(self.tableWidget, 1, 0, 1, 2) + self.layout.addWidget(self.interfbtn, 0, 1) + self.layout.addWidget(self.refreshbtn, 0, 2) + self.layout.addWidget(self.tableWidget, 1, 0, 1, 3) self.setLayout(self.layout) @@ -36,8 +43,8 @@ class NetworkDevices(QWidget): self.tableWidget.setShowGrid(True) self.tableWidget.setGridStyle(Qt.NoPen) self.tableWidget.setRowCount(0) - self.tableWidget.setColumnCount(3) - self.tableWidget.setHorizontalHeaderLabels(["IP", "MAC", "Status"]) + self.tableWidget.setColumnCount(2) + self.tableWidget.setHorizontalHeaderLabels(["IP", "MAC"]) self.tableWidget.horizontalHeader().setVisible(True) self.tableWidget.horizontalHeader().setCascadingSectionResizes(True) self.tableWidget.horizontalHeader().setHighlightSections(False) @@ -54,21 +61,47 @@ class NetworkDevices(QWidget): sizePolicy.setHeightForWidth( self.tableWidget.sizePolicy().hasHeightForWidth()) self.tableWidget.setSizePolicy(sizePolicy) + + def getConnectedDevices(self): + while self.networkIP is '': + sys.stdout.write('\a') + sys.stdout.flush() + self.networkInterface() + + output = subprocess.check_output(["arp", "-a"]) #get ARP table + output = output.partition(bytes(f"Interface: {self.networkIP}", 'utf-8'))[2] + output = output.split(b'Interface')[0] + output = output.split()[7:] + + self.tableWidget.clearContents() + self.tableWidget.setRowCount(0) - def refreshStatus(self): - target_ip = "192.168.1.1/16" - packet = Ether("ff:ff:ff:ff:ff:ff")/ARP(pdst=target_ip) + for i in range(0, len(output), 3): + entry_ip = str(output[i], encoding='utf-8') + entry_mac = str(output[i+1], encoding='utf-8').replace("-",":") + + mul_addr = int(entry_ip.split('.')[0]) + if mul_addr >= 224 and mul_addr < 240: + continue - result = srp1(packet, timeout=2, verbose=0) + arpData = dict() + arpData['IP'] = entry_ip + arpData['MAC'] = entry_mac - if result is not None: - devices = [] - for sent, received in result: - # for each response, append ip and mac address to `clients` list - devices.append({'ip': received.psrc, 'mac': received.hwsrc}) + self.addArpToTableWidget(arpData) + + def addArpToTableWidget(self, arpData): + rowpos = self.tableWidget.rowCount() + self.tableWidget.insertRow(rowpos) + self.tableWidget.setItem(rowpos, 0, QTableWidgetItem(arpData['IP'])) + self.tableWidget.setItem(rowpos, 1, QTableWidgetItem(arpData['MAC'])) - # print clients - print("Available devices in the network:") - print("IP" + " "*18+"MAC") - for client in devices: - print("{:16} {}".format(client['ip'], client['mac'])) \ No newline at end of file + self.vbar = self.tableWidget.verticalScrollBar() + self._scroll = self.vbar.value() == self.vbar.maximum() + + def networkInterface(self): + self.interfaceDiag = InterfacePick() + self.interfaceDiag.exec_() + if hasattr(self.interfaceDiag, 'interfaceIP') and hasattr(self.interfaceDiag, 'interfaceName'): + self.networkIP = self.interfaceDiag.interfaceIP + self.interfbtn.setText(self.interfaceDiag.interfaceName) \ No newline at end of file diff --git a/network_monitor.py b/network_monitor.py index 6d59282..31f7bda 100644 --- a/network_monitor.py +++ b/network_monitor.py @@ -232,6 +232,7 @@ class InterfacePick(QDialog): def acceptInterfaceFn(self): self.idx = self.interfaceList.selectedIndexes() - self.interfaceName = self.idx[0].data().split('\t')[0].strip() + self.interfaceName = self.idx[0].data().split('\t')[0].strip() + self.interfaceIP = self.idx[0].data().split('\t')[1].strip() self.close() diff --git a/ping.py b/ping.py index db0b7ec..6c8df51 100644 --- a/ping.py +++ b/ping.py @@ -30,28 +30,27 @@ class Ping(QWidget): if(len(self.host.text()) >= 1): try: packet = IP(dst=self.host.text())/ICMP() - output = sr1(packet, timeout=2) - if output is not None: - res_type = icmptypes[output.type] - res_code = "" - if output.type in icmpcodes: - res_code = " - "+icmpcodes[output.type][output.code] - ping_time = int((output.time - packet.sent_time)*1000) + result = "" + + for i in range(1, 6): + output = sr1(packet, timeout=3, verbose=0) + if output is not None: + res_type = icmptypes[output.type] + res_code = "" + if output.type in icmpcodes: + res_code = " - "+icmpcodes[output.type][output.code] + ping_time = int((output.time - packet.sent_time)*1000) - self.result.setText( - "Ping results:\nSummary: {}\n\nType:\t\t{}{}\nTime:\t\t{}ms\nSource:\t\t{}\nDestination:\t{}\ - \nTTL:\t\t{}".format( - output.summary(), - res_type, - res_code, - ping_time, - packet[IP].src, - packet[IP].dst, - packet[IP].ttl + result += "{}{} from {}:\ttime={}ms\tTTL={}\n".format( + res_type, + res_code, + packet[IP].dst, + ping_time, + packet[IP].ttl ) - ) - else: - self.result.setText("Request timed out.") + else: + result += "Request timed out.\n" + self.result.setText(result) except socket.gaierror: self.result.setText( "Invalid address/Could not get address info") diff --git a/trace_route.py b/trace_route.py index d25a57e..7ddc47c 100644 --- a/trace_route.py +++ b/trace_route.py @@ -30,18 +30,22 @@ class TraceRoute(QWidget): if(len(self.host.text()) >= 1): try: result, unans = traceroute( - target=self.host.text(), dport=80, verbose=0) + target=self.host.text(), dport=80, verbose=0, timeout=3) output = [] output.append("\tRoute path\t\tResponse time") result = sorted(result, key=lambda x: x[0].ttl) + prev_rcv_src = '' for snd, rcv in result: + if prev_rcv_src == rcv.src: + break output.append( str("{}\t{}\t\t{} ms".format( snd.ttl, rcv.src, (int((rcv.time - snd.sent_time)*1000)) ))) + prev_rcv_src = rcv.src output.append("\nUnanswered packets: {}".format( len(unans) ))