def run(self): """ Copies the firmware image onto the Router, proves if the firmware is in the right file(/tmp/<firmware_name>.bin) and does a Sysupgrade. :return: """ network_ctrl = NetworkCtrl(self.router) try: network_ctrl.connect_with_remote_system() except Exception as e: logging.warning("[-] Couldn't sysupgrade the Router(" + str(self.router.id) + ")") logging.warning(str(e)) return network_ctrl.remote_system_wget(self.router.firmware.file, '/tmp/', self.web_server_ip) # sysupgrade -n <firmware_name> // -n verwirft die letzte firmware arg = '-n' if self.n else '' if not self.debug: logging.debug("sysupgrade ...") try: network_ctrl.send_command('sysupgrade ' + arg + ' ' + '/tmp/' + self.router.firmware.name) except TimeoutError: logging.info("%s[+] Router was set into normal mode", LoggerSetup.get_log_deep(2)) self.router.mode = Mode.configuration if Dhclient.update_ip(self.router.vlan_iface_name) == 1: self.router.mode = Mode.unknown logging.error("%s[-] Something went wrong. Use command 'online -r " + str(self.router.id) + "'", LoggerSetup.get_log_deep(2)) except Exception as e: self.router.mode = Mode.unknown logging.error("[-] Something went wrong. Use command 'online -r " + str(self.router.id) + "'") logging.error(str(e)) network_ctrl.exit()
def test_router_wget(self): # Create router router = Router(1, "vlan1", 21, "10.223.254.254", 16, "192.168.1.1", 24, "root", "root", 1) router.model = "TP-LINK TL-WR841N/ND v9" router.mac = "e8:de:27:b7:7c:e2" # Has to be matched with the current mode (normal, configuration) router.mode = Mode.configuration assert isinstance(router, Router) # Create NetworkCrtl network_ctrl = NetworkCtrl(router, 'eth0') assert isinstance(network_ctrl, NetworkCtrl) self.assertRaises(Exception, network_ctrl.connect_with_remote_system()) # Create test file 'test_wget.txt' path = os.path.dirname(__file__) file = open(path + '/test_wget.txt', 'w+') # The Router downloads this file via wget from the raspberryPi network_ctrl.remote_system_wget(path + '/test_wget.txt', '/tmp/') # Tests if the file has successful downloaded output = network_ctrl.send_command( "test -f '/tmp/test_wget.txt' && echo True") self.assertEqual(output, "['True\\n']") # Test output = network_ctrl.send_command( "rm '/tmp/test_wget.txt' && echo True") self.assertEqual(output, "['True\\n']") file.close() network_ctrl.exit()
def test_router_wget(self): # Create router router = Router(1, "vlan1", 21, "10.223.254.254", 16, "192.168.1.1", 24, "root", "root", 1) router.model = "TP-LINK TL-WR841N/ND v9" router.mac = "e8:de:27:b7:7c:e2" # Has to be matched with the current mode (normal, configuration) router.mode = Mode.configuration assert isinstance(router, Router) # Create NetworkCrtl network_ctrl = NetworkCtrl(router, 'eth0') assert isinstance(network_ctrl, NetworkCtrl) self.assertRaises(Exception, network_ctrl.connect_with_remote_system()) # Create test file 'test_wget.txt' path = os.path.dirname(__file__) file = open(path + '/test_wget.txt', 'w+') # The Router downloads this file via wget from the raspberryPi network_ctrl.remote_system_wget(path + '/test_wget.txt', '/tmp/') # Tests if the file has successful downloaded output = network_ctrl.send_command("test -f '/tmp/test_wget.txt' && echo True") self.assertEqual(output, "['True\\n']") # Test output = network_ctrl.send_command("rm '/tmp/test_wget.txt' && echo True") self.assertEqual(output, "['True\\n']") file.close() network_ctrl.exit()
def test_connection(self): """ Test: 1. Google or FreiFunk is reachable via a Ping """ logging.debug("%sTest: Existence of an Internet-Connection", LoggerSetup.get_log_deep(1)) assert self.remote_system.mode == Mode.normal logging.debug("%s[" + u"\u2714" + "] Correct Mode", LoggerSetup.get_log_deep(2)) network_ctrl = NetworkCtrl(self.remote_system) network_ctrl.connect_with_remote_system() ping_result1 = network_ctrl.send_command( "ping -c 5 8.8.8.8 | grep received") ping_result2 = network_ctrl.send_command( "ping -c 5 freifunk.net | grep received") self.assertTrue( self._ping_successful(ping_result1[0]) or self._ping_successful(ping_result2[0]), "No Internet-Connection") logging.debug( "%s[" + u"\u2714" + "] At least one Ping was successful => An Internet-Connection exist", LoggerSetup.get_log_deep(2)) network_ctrl.exit()
def test_setup_expert(self): """ This UnitTest executes the wca_setup_expert-function with the given config-file. It sets the values of all the from WebInterface of the Router. """ # Create router router = Router(1, "vlan1", 21, "10.223.254.254", 16, "192.168.1.1", 24, "root", "root", 1) router.model = "TP-LINK TL-WR841N/ND v9" router.mac = "e8:de:27:b7:7c:e2" router.mode = Mode.configuration assert isinstance(router, Router) # Config config = ConfigManager().get_web_interface_dict()[0] self.assertEqual(len(config), 30, "Wrong size of the Config-Directory") # Create NetworkCrtl network_ctrl = NetworkCtrl(router, 'eth0') assert isinstance(network_ctrl, NetworkCtrl) try: web_config_assist = RouterWebConfiguration(router, config, wizard=True) web_config_assist.start() web_config_assist.join() except Exception as e: Logger().error(str(e)) finally: assert router.mode == Mode.normal network_ctrl.exit()
def run(self): """ Copies the firmware image onto the Router, proves if the firmware is in the right file(/tmp/<firmware_name>.bin) and does a Sysupgrade. """ network_ctrl = NetworkCtrl(self.router) try: network_ctrl.connect_with_remote_system() except Exception as e: logging.warning("%s[-] Couldn't sysupgrade the Router(" + str(self.router.id) + ")", LoggerSetup.get_log_deep(2)) logging.warning(str(e)) return network_ctrl.remote_system_wget(self.router.firmware.file, '/tmp/', self.web_server_ip) # sysupgrade -n <firmware_name> // -n verwirft die letzte firmware arg = '-n' if self.n else '' if not self.debug: logging.debug("%sSysupgrade (this will force a TimeoutError)...", LoggerSetup.get_log_deep(2)) try: network_ctrl.send_command('sysupgrade ' + arg + ' ' + '/tmp/' + self.router.firmware.name) except TimeoutError: try: Dhclient.update_ip(self.router.vlan_iface_name) self._success_handling() except FileExistsError: self._success_handling() pass except Exception: self._execption_hanling() except Exception: self._execption_hanling() network_ctrl.exit()
def run(self): """ Instantiate a NetworkCtrl and setup the webinterface of the Router """ Logger().info("Sysupdate Firmware for Router(" + str(self.router.id) + ") ...") network_ctrl = NetworkCtrl(self.router, 'eth0') network_ctrl.wca_setup_expert(self.webinterface_config) network_ctrl.wca_setup_wizard(self.webinterface_config) network_ctrl.exit()
def run(self): """ Instantiate a NetworkCtrl, proves if the firmware is on the Router(/tmp/<firmware_name>.bin) and does a Sysupgrade. :return: """ network_ctrl = NetworkCtrl(self.router, 'eth0') network_ctrl.connect_with_remote_system() network_ctrl.remote_system_wget(self.router.firmware.file, '/tmp/') # sysupgrade -n <firmware_name> // -n verwirft die letzte firmware arg = '-n' if self.n else '' network_ctrl.send_command('sysupgrade ' + arg + ' ' + '/tmp/' + self.router.firmware.name) network_ctrl.exit()
def test_connection(self): # Create router router = Router(1, "vlan1", 21, "10.223.254.254", 16, "192.168.1.1", 24, "root", "root", 1) router.model = "TP-LINK TL-WR841N/ND v9" router.mac = "e8:de:27:b7:7c:e2" # Has to be matched with the current mode (normal, configuration) router.mode = Mode.configuration assert isinstance(router, Router) # Create NetworkCrtl network_ctrl = NetworkCtrl(router, 'eth0') assert isinstance(network_ctrl, NetworkCtrl) # network_ctrl.connect_with_router() network_ctrl.exit()
def test_send_command(self): # Create router router = Router(1, "vlan1", 21, "10.223.254.254", 16, "192.168.1.1", 24, "root", "root", 1) router.model = "TP-LINK TL-WR841N/ND v9" router.mac = "e8:de:27:b7:7c:e2" # Has to be matched with the current mode (normal, configuration) router.mode = Mode.configuration assert isinstance(router, Router) # Create NetworkCrtl network_ctrl = NetworkCtrl(router, 'eth0') assert isinstance(network_ctrl, NetworkCtrl) # Test if the command 'uname' could be send via ssh self.assertRaises(Exception, network_ctrl.connect_with_remote_system()) output = network_ctrl.send_command("uname") self.assertEqual(output, "['Linux\\n']") network_ctrl.exit()
def test_connection(self): """ Test: 1. Google or FreiFunk is reachable via a Ping """ logging.debug("%sTest: Existence of an Internet-Connection", LoggerSetup.get_log_deep(1)) assert self.remote_system.mode == Mode.normal logging.debug("%s[" + u"\u2714" + "] Correct Mode", LoggerSetup.get_log_deep(2)) network_ctrl = NetworkCtrl(self.remote_system) network_ctrl.connect_with_remote_system() ping_result1 = network_ctrl.send_command("ping -c 5 8.8.8.8 | grep received") ping_result2 = network_ctrl.send_command("ping -c 5 freifunk.net | grep received") self.assertTrue(self._ping_successful(ping_result1[0]) or self._ping_successful(ping_result2[0]), "No Internet-Connection") logging.debug("%s[" + u"\u2714" + "] At least one Ping was successful => An Internet-Connection exist", LoggerSetup.get_log_deep(2)) network_ctrl.exit()
def run(self): """ Runs new thread and gets the information from the router via ssh :return: """ network_ctrl = NetworkCtrl(self.router, 'eth0') network_ctrl.connect_with_remote_system() # Model self.router.model = network_ctrl.send_command( 'cat /proc/cpuinfo | grep machine').split(":")[1][:-4] # MAC self.router.mac = network_ctrl.send_command( 'uci show network.client.macaddr').split('=')[1][:-4] # SSID self.router.ssid = network_ctrl.send_command( 'uci show wireless.client_radio0.ssid').split('=')[1][:-4] network_ctrl.exit()
def test_setup_expert(self): """ This UnitTest executes the wca_setup_expert-function with the given config-file. It sets the values of all the from WebInterface of the Router. """ # Create router router = Router(1, "vlan1", 21, "10.223.254.254", 16, "192.168.1.1", 24, "root", "root", 1) router.model = "TP-LINK TL-WR841N/ND v9" router.mac = "e8:de:27:b7:7c:e2" router.mode = Mode.configuration assert isinstance(router, Router) # Config config = ConfigManager().get_web_interface_dict()[0] self.assertEqual(len(config), 30, "Wrong size of the Config-Directory") # Create NetworkCrtl network_ctrl = NetworkCtrl(router, "eth0") assert isinstance(network_ctrl, NetworkCtrl) self.assertRaises(Exception, network_ctrl.wca_setup_expert(config)) network_ctrl.exit()
def run(self): """ Runs new thread and trys to send a command via ssh to reboot the Router. """ network_ctrl = NetworkCtrl(self.router, "eth0") network_ctrl.connect_with_remote_system() if self.configmode: if self.router.mode == Mode.configuration: Logger().info("[+] Router is already in configuration mode", 2) network_ctrl.exit() return try: network_ctrl.send_command("uci set 'gluon-setup-mode.@setup_mode[0].enabled=1'") network_ctrl.send_command("uci commit") network_ctrl.send_command("reboot") self.router.mode = Mode.configuration except Exception as e: Logger().warning("[-] Couldn't set Router into configuration mode", 2) Logger().error(str(e), 2) Logger().info("[+] Router was set into configuration mode", 2) else: if self.router.mode == Mode.normal: Logger().info("[+] Router is already in normal mode", 2) network_ctrl.exit() return try: network_ctrl.send_command("reboot") self.router.mode = Mode.normal Logger().info("[+] Router was set into normal mode", 2) except Exception as e: Logger().warning("[-] Couldn't set Router into normal mode", 2) Logger().error(str(e), 2) network_ctrl.exit()
def run(self): """ Runs new thread and trys to send a command via ssh to reboot the Router. """ logging.info("%sReboot the Router(" + str(self.router.id) + ") ...", LoggerSetup.get_log_deep(1)) network_ctrl = NetworkCtrl(self.router) try: network_ctrl.connect_with_remote_system() except Exception as e: logging.error("%s[-] Couldn't reboot Router(" + str(self.router.id) + ")", LoggerSetup.get_log_deep(2)) logging.error("%s" + str(e), LoggerSetup.get_log_deep(2)) network_ctrl.exit() return # Reboot Router into configuration-mode if self.configmode: if self.router.mode == Mode.configuration: logging.info("%s[+] Router is already in " + str(Mode.configuration), LoggerSetup.get_log_deep(2)) network_ctrl.exit() return try: network_ctrl.send_command("uci set 'gluon-setup-mode.@setup_mode[0].enabled=1'") network_ctrl.send_command("uci commit") network_ctrl.send_command("reboot") logging.info("%sWait until Router rebooted (60sec) ...", LoggerSetup.get_log_deep(2)) time.sleep(60) Dhclient.update_ip(self.router.vlan_iface_name) self._success_handling() except FileExistsError: self._success_handling() pass except Exception as e: self._execption_hanling() # Reboot Router into normal-mode else: if self.router.mode == Mode.normal: logging.info("%s[+] Router is already in " + str(Mode.normal), LoggerSetup.get_log_deep(2)) network_ctrl.exit() return try: network_ctrl.send_command("reboot") logging.info("%sWait until Router rebooted (90sec) ...", LoggerSetup.get_log_deep(2)) time.sleep(90) Dhclient.update_ip(self.router.vlan_iface_name) self._success_handling() except FileExistsError: self._success_handling() pass except Exception as e: self._execption_hanling() network_ctrl.exit()
class PowerStripControl(Thread): def __init__(self, power_strip: Ubnt, on_or_off: bool, port: int): Thread.__init__(self) self.power_strip = power_strip self.on_or_off = on_or_off self.port = port self.network_ctrl = NetworkCtrl(self.power_strip) self.daemon = True def run(self): """ Runs new thread """ self.network_ctrl.connect_with_remote_system() cmd = self.create_command(self.on_or_off, self.port) self.network_ctrl.send_command(cmd) check = self._port_status(self.port) result = self.network_ctrl.send_command(check) result = result[0] if self.on_or_off: if result == "1": logging.info("[+] Successfully switched on port " + str(self.port)) else: logging.info("[-] Error switching on port " + str(self.port)) else: if result == "0": logging.info("[+] Successfully switched off port " + str(self.port)) else: logging.info("[-] Error switching off port " + str(self.port)) self.network_ctrl.exit() def create_command(self, on_or_off: bool, port: int): return self.power_strip.create_command(port, on_or_off) def _port_status(self, port: int): return self.power_strip.port_status(port)
def run(self): """ Copies the firmware image onto the Router, proves if the firmware is in the right file(/tmp/<firmware_name>.bin) and does a Sysupgrade. :return: """ network_ctrl = NetworkCtrl(self.router) try: network_ctrl.connect_with_remote_system() except Exception as e: logging.warning("[-] Couldn't sysupgrade the Router(" + str(self.router.id) + ")") logging.warning(str(e)) return network_ctrl.remote_system_wget(self.router.firmware.file, '/tmp/', self.web_server_ip) # sysupgrade -n <firmware_name> // -n verwirft die letzte firmware arg = '-n' if self.n else '' if not self.debug: logging.debug("sysupgrade ...") try: network_ctrl.send_command('sysupgrade ' + arg + ' ' + '/tmp/' + self.router.firmware.name) except TimeoutError: logging.info("%s[+] Router was set into normal mode", LoggerSetup.get_log_deep(2)) self.router.mode = Mode.configuration if Dhclient.update_ip(self.router.vlan_iface_name) == 1: self.router.mode = Mode.unknown logging.error( "%s[-] Something went wrong. Use command 'online -r " + str(self.router.id) + "'", LoggerSetup.get_log_deep(2)) except Exception as e: self.router.mode = Mode.unknown logging.error( "[-] Something went wrong. Use command 'online -r " + str(self.router.id) + "'") logging.error(str(e)) network_ctrl.exit()
def test_setup_expert(self): """ This UnitTest executes the wca_setup_expert-function with the given config-file. It sets the values of all the from WebInterface of the Router. """ # Create router router = Router(1, "vlan1", 21, "10.223.254.254", 16, "192.168.1.1", 24, "root", "root", 1) router.model = "TP-LINK TL-WR841N/ND v9" router.mac = "e8:de:27:b7:7c:e2" router.mode = Mode.configuration assert isinstance(router, Router) # Config config = ConfigManager().get_web_interface_dict()[0] self.assertEqual(len(config), 30, "Wrong size of the Config-Directory") # Create NetworkCrtl network_ctrl = NetworkCtrl(router, 'eth0') assert isinstance(network_ctrl, NetworkCtrl) self.assertRaises(Exception, network_ctrl.wca_setup_expert(config)) network_ctrl.exit()
def run(self): """ Copies the firmware image onto the Router, proves if the firmware is in the right file(/tmp/<firmware_name>.bin) and does a Sysupgrade. """ network_ctrl = NetworkCtrl(self.router) try: network_ctrl.connect_with_remote_system() except Exception as e: logging.warning( "%s[-] Couldn't sysupgrade the Router(" + str(self.router.id) + ")", LoggerSetup.get_log_deep(2)) logging.warning(str(e)) return network_ctrl.remote_system_wget(self.router.firmware.file, '/tmp/', self.web_server_ip) # sysupgrade -n <firmware_name> // -n verwirft die letzte firmware arg = '-n' if self.n else '' if not self.debug: logging.debug("%sSysupgrade (this will force a TimeoutError)...", LoggerSetup.get_log_deep(2)) try: network_ctrl.send_command('sysupgrade ' + arg + ' ' + '/tmp/' + self.router.firmware.name) except TimeoutError: try: Dhclient.update_ip(self.router.vlan_iface_name) self._success_handling() except FileExistsError: self._success_handling() pass except Exception: self._execption_hanling() except Exception: self._execption_hanling() network_ctrl.exit()
def run(self): """ Runs new thread and trys to send a command via ssh to reboot the Router. """ network_ctrl = NetworkCtrl(self.router, 'eth0') network_ctrl.connect_with_remote_system() if self.configmode: if self.router.mode == Mode.configuration: Logger().info("[+] Router is already in configuration mode", 2) network_ctrl.exit() return try: network_ctrl.send_command( "uci set 'gluon-setup-mode.@setup_mode[0].enabled=1'") network_ctrl.send_command("uci commit") network_ctrl.send_command("reboot") self.router.mode = Mode.configuration except Exception as e: Logger().warning( "[-] Couldn't set Router into configuration mode", 2) Logger().error(str(e), 2) Logger().info("[+] Router was set into configuration mode", 2) else: if self.router.mode == Mode.normal: Logger().info("[+] Router is already in normal mode", 2) network_ctrl.exit() return try: network_ctrl.send_command("reboot") self.router.mode = Mode.normal Logger().info("[+] Router was set into normal mode", 2) except Exception as e: Logger().warning("[-] Couldn't set Router into normal mode", 2) Logger().error(str(e), 2) network_ctrl.exit()
class RouterInfo(Thread): """ The RouterInfo collects in a new Thread informations about the Routers. This class gets the following information via SSH: 1. RouterModel 2. MAC-Address 3. Network-Interfaces 4. CPU-Processes-Information 5. Memory-Information 6. Sockets 7. UCI-Configurations 8. Bat-Originators """"" def __init__(self, router: Router): """ :param router: Router-Obj """ Thread.__init__(self) self.router = router self.network_ctrl = NetworkCtrl(self.router) self.daemon = True def run(self): """ Runs new thread and gets the information from the Router via ssh. """ logging.info("%sUpdate the Infos of the Router(" + str(self.router.id) + ") ...", LoggerSetup.get_log_deep(1)) try: self.network_ctrl.connect_with_remote_system() # Model self.router.model = self._get_router_model() # MAC self.router.mac = self._get_router_mac() # NetworkInterfaces self.router.network_interfaces = self._get_router_network_interfaces() # CPUProcesses self.router.cpu_processes = self._get_router_cpu_process() # RAM self.router.ram = self._get_router_mem_ram() # Sockets self.router.sockets = self._get_router_sockets() # UCI self.router.uci = self._get_router_uci() # Bat Originators self.router.bat_originators = self._get_bat_originator() logging.info("%s[+] Infos updated", LoggerSetup.get_log_deep(2)) except Exception as e: logging.error("%s[-] Couldn't update all Infos", LoggerSetup.get_log_deep(2)) logging.error(str(e)) for tb in traceback.format_tb(sys.exc_info()[2]): logging.error("%s" + tb, LoggerSetup.get_log_deep(3)) finally: self.network_ctrl.exit() def _get_router_model(self) -> str: """ :return: the Model of the given Router object """ return self.network_ctrl.send_command('cat /proc/cpuinfo | grep machine')[0].split(":")[1][1:-1] def _get_router_mac(self) -> str: """ :return: the MAC of the given Router object """ return self.network_ctrl.send_command('uci show network.client.macaddr')[0].split('=')[1][:-1] def _get_router_ssid(self): """ :return: the SSID of the given Router object """ return self.network_ctrl.send_command('uci show wireless.client_radio0.ssid')[0].split('=')[1][:-1] def _get_router_network_interfaces(self) -> Dict: """ :return: the network interfaces of the given Router object """ interfaces = dict() # Get all network interfaces raw_iface_lst = self.network_ctrl.send_command("ip a | grep '^[0-9]*:*:'") iface_names_lst = list() iface_id_lst = list() # Get only the wifi interfaces raw_wifi_inface_name_lst = self.network_ctrl.send_command("iw dev | grep Interface") wifi_iface_name_lst = list() for raw_wifi_iface_name in raw_wifi_inface_name_lst: wifi_iface_name_lst.append(raw_wifi_iface_name.split("Interface ")[1].replace("\n", "")) # transform a line tmp: # '2: enp0s25: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000' # into '2'; 'enp0s25' and lists it. for raw_iface in raw_iface_lst: # Iface Id iface_id = int(raw_iface.split(":")[0]) if iface_id_lst.count(iface_id) == 0: iface_id_lst.append(iface_id) # Iface Name iface_name = raw_iface.split(":")[1].replace(" ", "") if "@" in iface_name: iface_name = iface_name.split("@")[0] if iface_names_lst.count(iface_name) == 0: iface_names_lst.append(iface_name) # Take the information of the interfaces separately for i, iface_id in enumerate(iface_id_lst): iface_name = iface_names_lst[i] interface = NetworkInterface(iface_id, iface_name) raw_iface_info_lst = self.network_ctrl.send_command("ip addr show " + iface_name) for raw_iface_info in raw_iface_info_lst: # Status raw_status = raw_iface_info.split("state") if len(raw_status) > 1: status = raw_status[1].split(" ")[1] # Status: UP | DOWN | UNKNOWN if status == "UP": interface.status = Status.up elif status == "DOWN": interface.status = Status.down else: interface.status = Status.unknown # MAC raw_mac = raw_iface_info.split("link/ether") if len(raw_mac) > 1: raw_mac = raw_mac[1].split() interface.mac = raw_mac[0] # IP Address raw_ip = raw_iface_info.split("inet") if len(raw_ip) > 1: raw_ip = raw_ip[1].split(" ")[1].split("/") interface.add_ip_address(raw_ip[0], int(raw_ip[1])) # Wifi information if wifi_iface_name_lst.count(iface_name) != 0: interface.wifi_information = self.__get_wifi_information(iface_name) interfaces[iface_name] = interface return interfaces def __get_wifi_information(self, iface_name: str) -> WifiInformation: """ If the given interface name belongs to an wifi interface, there are some more infomations. :param iface_name: Name of the network interface :return: WifiInformation """ wifi_information = WifiInformation() raw_wifi_info_lst = self.network_ctrl.send_command("iw dev") right_iface = False for raw_wifi_info in raw_wifi_info_lst: raw_wifi_info = raw_wifi_info.replace("\n", "") if "Interface" in raw_wifi_info: right_iface = True if iface_name in raw_wifi_info else False elif right_iface: if "wdev" in raw_wifi_info: wifi_information.wdev = raw_wifi_info.split(" ")[1] elif "ssid" in raw_wifi_info: wifi_information.ssid = raw_wifi_info.split(" ")[1] elif "type" in raw_wifi_info: wifi_information.type = raw_wifi_info.split(" ")[1] elif "channel" in raw_wifi_info: wifi_information.channel = int(raw_wifi_info.split(" ")[1]) wifi_information.channel_width = int(raw_wifi_info.split(" ")[5]) wifi_information.channel_center1 = int(raw_wifi_info.split(" ")[8]) return wifi_information def _get_router_cpu_process(self) -> List: """ :return: The cpu processes of the given Router object """ cpu_processes = list() raw_cpu_process_lst = self.network_ctrl.send_command("top -n 1") # A line looks like: # 1051 1020 root R 1388 5% 9% firefox for cpu_process_info_line in raw_cpu_process_lst[4:]: cpu_process_info_lst = cpu_process_info_line.split() if len(cpu_process_info_lst) > 7: # Get the infos pid = int(cpu_process_info_lst[0]) user = cpu_process_info_lst[2] mem = float(cpu_process_info_lst[5].replace("%", "")) cpu = float(cpu_process_info_lst[6].replace("%", "")) command = "" for i in range(7, len(cpu_process_info_lst)): command += cpu_process_info_lst[i] cpu_process = CPUProcess(pid, user, mem, cpu, command) cpu_processes.append(cpu_process) return cpu_processes def _get_router_mem_ram(self) -> RAM: """ :return: The RAM of the given Router. """ ram = None raw_mem_lst = self.network_ctrl.send_command("free -m")[1:] for ram_info_line in raw_mem_lst: if "Mem" in ram_info_line: # Split and remove the spaces ram_info_lst = ram_info_line.split() # Get the infos total = int(ram_info_lst[1]) used = int(ram_info_lst[2]) free = int(ram_info_lst[3]) shared = int(ram_info_lst[4]) buffers = int(ram_info_lst[5]) ram = RAM(total, used, free, shared, buffers) return ram def _get_router_sockets(self) -> List: """ :return: The Sockets of the Router. """ socket_lst = list() raw_socket_lst = self.network_ctrl.send_command("netstat -taupn")[2:] for raw_socket in raw_socket_lst: # raw_socket looks like: # tcp 0 32 192.168.1.1:22 192.168.1.239:51891 ESTABLISHED 1067/dropbear raw_socket = raw_socket.split() socket = InternetSocket() socket.protocol = raw_socket[0] raw_local_address = raw_socket[3].split(":") socket.local_address = raw_local_address[0] if len(raw_local_address) == 2 else "::" socket.local_port = raw_local_address[-1] raw_foreign_address = raw_socket[4].split(":") socket.foreign_address = raw_foreign_address[0] if len(raw_foreign_address) == 2 else "::" socket.foreign_port = raw_foreign_address[-1] raw_process = "-1/error" if raw_socket[0] == "tcp": socket.state = raw_socket[5] raw_process = raw_socket[6].split("/") elif raw_socket[0] == "udp": raw_process = raw_socket[5].split("/") socket.pid = int(raw_process[0]) socket.program_name = raw_process[1] socket_lst.append(socket) return socket_lst def _get_router_uci(self): """ :return: All values of the UCI of a Router. """ uci_dict = dict() raw_uci_lst = self.network_ctrl.send_command("uci show") for uci_info in raw_uci_lst: key, value = uci_info.split("=") uci_dict[key] = value.replace("\n", "") return uci_dict def _get_bat_originator(self): """ :return: All reachable mesh-nodes(bat_originators) of a Router. """ bat_originators = list() raw_bat_originator_lst = self.network_ctrl.send_command("batctl o")[2:] for raw_bat_originator in raw_bat_originator_lst: raw_bat_originator = raw_bat_originator.replace("( ", "(").replace("[ ", "").split() # raw_bat_originator: ['f6:f6:6d:85:d4:ae', '0.840s', '(52)', '32:b8:c3:e7:6f:f0', 'mesh0]:', # '02:2a:1a:cc:72:ae', '(3)', '32:b8:c3:e7:96:b0', '(26)', '32:b8:c3:e7:6f:f0', '(52)'] mac = raw_bat_originator[0] tmp = raw_bat_originator[1].replace("s", "") last_seen = float(tmp) next_hop = raw_bat_originator[3] outgoing_iface = raw_bat_originator[4].replace("]:", "") potential_next_hops = list() for raw_potential_next_hop in raw_bat_originator[5:]: if ":" in raw_potential_next_hop: potential_next_hops.append(raw_potential_next_hop) bat_originator = BatOriginator(mac, last_seen, next_hop, outgoing_iface, potential_next_hops) bat_originators.append(bat_originator) return bat_originators
class PowerStripControl(Thread): """ This class controls the power strip. It can switch the power on a port. It also checks if the power was actually turned on/off. """"" def __init__(self, router: Router, power_strip: Ubnt, on_or_off: bool, port: int): """ :param router: Affected Router-Obj :param power_strip: Affected Powerstrip-Obj :param on_or_off: 'True' for on, 'False' for off :param port: ID of the powerstrip pot """ Thread.__init__(self) self.router = router self.power_strip = power_strip self.on_or_off = on_or_off self.port = port self.network_ctrl = NetworkCtrl(self.power_strip) self.daemon = True def run(self): """ Sets the power on the port to on/off. Also checks if the power is truly on/off. """ self.network_ctrl.connect_with_remote_system() cmd = self.create_command(self.on_or_off, self.port) self.network_ctrl.send_command(cmd) check = self._port_status(self.port) result = self.network_ctrl.send_command(check) result = result[0] if self.on_or_off: if result == "1": self.router.mode = Mode.normal logging.info("[+] Successfully switched on port " + str(self.port)) else: self.router.mode = Mode.unknown logging.info("[-] Error switching on port " + str(self.port)) else: if result == "0": self.router.mode = Mode.off logging.info("[+] Successfully switched off port " + str(self.port)) else: self.router.mode = Mode.unknown logging.info("[-] Error switching off port " + str(self.port)) self.network_ctrl.exit() def create_command(self, on_or_off: bool, port: int): """ Creates the command to turn the power on the given port on or off. :param on_or_off: 'True' for on, 'False' for off :param port: ID of the port :return: Command as a str to control the power on the port given """ return self.power_strip.create_command(port, on_or_off) def _port_status(self, port: int): return self.power_strip.port_status(port)
class RouterInfo(Thread): """ The RouterInfo collects in a new Thread informations about the Routers """"" def __init__(self, router: Router): Thread.__init__(self) self.router = router self.network_ctrl = NetworkCtrl(self.router, 'eth0') self.daemon = True def run(self): """ Runs new thread and gets the information from the router via ssh :return: """ Logger().info("Update the Infos of the Router(" + str(self.router.id) + ") ...", 1) self.network_ctrl.connect_with_remote_system() try: # Model self.router.model = self._get_router_model() # MAC self.router.mac = self._get_router_mac() # SSID self.router.ssid = self._get_router_ssid() # NetworkInterfaces self.router.interfaces = self._get_router_network_interfaces() # CPUProcesses self.router.cpu_processes = self._get_router_cpu_process() # RAM self.router.ram = self._get_router_mem_ram() Logger().debug("[+] Infos updated") except Exception as e: Logger().warning("[-] Couldn't update all Infos") Logger().error(str(e)) def join(self): self.network_ctrl.exit() Thread.join(self) def _get_router_model(self) -> str: """ :return: the Model of the given Router object """ return self.network_ctrl.send_command('cat /proc/cpuinfo | grep machine').split(":")[1][:-4] def _get_router_mac(self) -> str: """ :return: the MAC of the given Router object """ return self.network_ctrl.send_command('uci show network.client.macaddr').split('=')[1][:-4] def _get_router_ssid(self): """ :return: the SSID of the given Router object """ return self.network_ctrl.send_command('uci show wireless.client_radio0.ssid').split('=')[1][:-4] def _get_router_network_interfaces(self) -> Dict: """ :return: the network interfaces of the given Router object """ interfaces = dict() raw_iface_names = self.network_ctrl.send_command("ip a | grep '^[0-9]*:*:'").split("\\n'")[0:-1] iface_names = list() # transform a line tmp: # '2: enp0s25: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000' # into 'enp0s25' and lists it. for raw_iface_name in raw_iface_names: iface_name = raw_iface_name.split(":")[1].replace(" ", "") if "@" in iface_name: iface_name = iface_name.split("@")[0] if iface_names.count(iface_name) == 0: iface_names.append(iface_name) for iface_name in iface_names: interface = NetworkInterface(iface_name) # MAC raw_iface_infos = self.network_ctrl.send_command("ip addr show " + iface_name + " | grep 'link/ether'") raw_iface_infos = raw_iface_infos.replace("[", "").replace("]", "").replace("'", "") if len(raw_iface_infos) > 0: raw_mac = raw_iface_infos.split(" ") i = raw_mac.count("") for i in range(0, i): raw_mac.remove("") interface.mac = raw_mac[1] # Status raw_iface_infos = self.network_ctrl.send_command("ip addr show " + iface_name + " | grep " + iface_name) raw_iface_infos = raw_iface_infos.replace("[", "").replace("]", "").replace("'", "") raw_status = raw_iface_infos.split("state") if len(raw_status) > 1: status = raw_status[1].split(" ")[1] # Status: UP | DOWN | UNKNOWN if status == "UP": interface.status = Status.up elif status == "DOWN": interface.status = Status.down else: interface.status = Status.unknown # IPv4 addresses raw_iface_infos = self.network_ctrl.send_command("ip addr show " + iface_name + " | grep 'inet '") raw_iface_infos = raw_iface_infos.replace("[", "").replace("]", "").replace("'", "") if len(raw_iface_infos) > 0: inet_lst = raw_iface_infos.split("\\n") for inet in inet_lst: if not ("inet" in inet): continue ip = inet.split("/")[0].split("inet ")[1] ip_mask = int(inet.split("/")[1].split(" ")[0]) interface.ipv4_lst.append(IPv4(ip, ip_mask)) # IPv6 addresses raw_iface_infos = self.network_ctrl.send_command("ip addr show " + iface_name + " | grep 'inet6 '") raw_iface_infos = raw_iface_infos.replace("[", "").replace("]", "").replace("'", "") if len(raw_iface_infos) > 0: inet_lst = raw_iface_infos.split("\\n") for inet in inet_lst: if not ("inet6" in inet): continue ip = inet.split("/")[0].split("inet6 ")[1] ip_prefix_len = int(inet.split("/")[1].split(" ")[0]) interface.ipv6_lst.append(IPv6(ip, ip_prefix_len)) interfaces[iface_name] = interface return interfaces def _get_router_cpu_process(self) -> List: """ :return: the cpu processes of the given Router object """ cpu_processes = list() raw_cpu_process_info = self.network_ctrl.send_command("top -n 1") raw_cpu_process_info = raw_cpu_process_info.replace("[", "").replace("]", "").replace("'", "") raw_cpu_process_info = raw_cpu_process_info.replace(",", "").replace("%", "") raw_cpu_process_info = raw_cpu_process_info.split("\\n") # A line looks like: # 1051 1020 root R 1388 5% 9% firefox for cpu_process_info_line in raw_cpu_process_info[4:]: # Split and remove the spaces cpu_process_info_lst = cpu_process_info_line.split(" ") i = cpu_process_info_lst.count("") for i in range(0, i): cpu_process_info_lst.remove("") if len(cpu_process_info_lst) > 7: # Get the infos pid = int(cpu_process_info_lst[0]) user = cpu_process_info_lst[2] mem = float(cpu_process_info_lst[5]) cpu = float(cpu_process_info_lst[6]) command = "" for i in range(7, len(cpu_process_info_lst)): command += cpu_process_info_lst[i] cpu_process = CPUProcess(pid, user, mem, cpu, command) cpu_processes.append(cpu_process) return cpu_processes def _get_router_mem_ram(self) -> RAM: """ :return: the RAM of the given Router. """ ram = None raw_mem_infos = self.network_ctrl.send_command("free -m") raw_mem_infos = raw_mem_infos.replace("[", "").replace("]", "").replace("'", "").replace(",", "") raw_mem_infos = raw_mem_infos.split("\\n") for ram_info_line in raw_mem_infos: if "Mem" in ram_info_line: # Split and remove the spaces ram_info_lst = ram_info_line.split(" ") i = ram_info_lst.count("") for i in range(0, i): ram_info_lst.remove("") # Get the infos total = int(ram_info_lst[1]) used = int(ram_info_lst[2]) free = int(ram_info_lst[3]) shared = int(ram_info_lst[4]) buffers = int(ram_info_lst[5]) ram = RAM(total, used, free, shared, buffers) return ram
def run(self): """ Runs new thread and trys to send a command via ssh to reboot the Router. """ logging.info("%sReboot the Router(" + str(self.router.id) + ") ...", LoggerSetup.get_log_deep(1)) network_ctrl = NetworkCtrl(self.router) try: network_ctrl.connect_with_remote_system() except Exception as e: logging.warning("[-] Couldn't reboot Router(" + str(self.router.id) + ")") logging.warning(str(e)) network_ctrl.exit() return if self.configmode: if self.router.mode == Mode.configuration: logging.info("%s[+] Router is already in configuration mode", LoggerSetup.get_log_deep(2)) network_ctrl.exit() return try: network_ctrl.send_command( "uci set 'gluon-setup-mode.@setup_mode[0].enabled=1'") network_ctrl.send_command("uci commit") network_ctrl.send_command("reboot") logging.info("Wait until Router rebooted (45sec) ...") time.sleep(45) if Dhclient.update_ip(self.router.vlan_iface_name) == 0: self.router.mode = Mode.configuration logging.info( "%s[+] Router was set into configuration mode", LoggerSetup.get_log_deep(2)) else: network_ctrl.exit() raise Exception except Exception as e: logging.warning( "%s[-] Couldn't set Router into configuration mode", LoggerSetup.get_log_deep(2)) logging.error("%s" + str(e), LoggerSetup.get_log_deep(2)) else: if self.router.mode == Mode.normal: logging.info("%s[+] Router is already in normal mode", LoggerSetup.get_log_deep(2)) network_ctrl.exit() return try: network_ctrl.send_command("reboot") logging.info("Wait until Router rebooted (45sec) ...") time.sleep(45) if Dhclient.update_ip(self.router.vlan_iface_name) == 0: self.router.mode = Mode.normal logging.info("%s+] Router was set into normal mode", LoggerSetup.get_log_deep(2)) else: network_ctrl.exit() raise Exception except Exception as e: logging.warning("%s[-] Couldn't set Router into normal mode", LoggerSetup.get_log_deep(2)) logging.error("%s" + str(e), LoggerSetup.get_log_deep(2)) network_ctrl.exit()
class RouterInfo(Thread): """ This class gets the following information via SSH: 1. RouterModel 2. MAC-Address 3. SSID 4. NetworkInterfaces 5. CPU-Processes-Information 6. Memory-Information 7. Sockets """ "" def __init__(self, router: Router): Thread.__init__(self) self.router = router self.network_ctrl = NetworkCtrl(self.router) self.daemon = True def run(self): """ Runs new thread and gets the information from the Router via ssh """ logging.info( "%sUpdate the Infos of the Router(" + str(self.router.id) + ") ...", LoggerSetup.get_log_deep(1)) try: self.network_ctrl.connect_with_remote_system() # Model self.router.model = self._get_router_model() # MAC self.router.mac = self._get_router_mac() # SSID self.router.ssid = self._get_router_ssid() # NetworkInterfaces self.router.interfaces = self._get_router_network_interfaces() # CPUProcesses self.router.cpu_processes = self._get_router_cpu_process() # RAM self.router.ram = self._get_router_mem_ram() # Sockets self.router.sockets = self._get_router_sockets() logging.debug("%s[+] Infos updated", LoggerSetup.get_log_deep(2)) except Exception as e: logging.warning("%s[-] Couldn't update all Infos", LoggerSetup.get_log_deep(2)) logging.error(str(e)) for tb in traceback.format_tb(sys.exc_info()[2]): logging.error("%s" + tb, LoggerSetup.get_log_deep(3)) finally: self.network_ctrl.exit() def _get_router_model(self) -> str: """ :return: the Model of the given Router object """ return self.network_ctrl.send_command( 'cat /proc/cpuinfo | grep machine')[0].split(":")[1][1:-1] def _get_router_mac(self) -> str: """ :return: the MAC of the given Router object """ return self.network_ctrl.send_command( 'uci show network.client.macaddr')[0].split('=')[1][:-1] def _get_router_ssid(self): """ :return: the SSID of the given Router object """ return self.network_ctrl.send_command( 'uci show wireless.client_radio0.ssid')[0].split('=')[1][:-1] def _get_router_network_interfaces(self) -> Dict: """ :return: the network interfaces of the given Router object """ interfaces = dict() # Get all network interfaces raw_iface_lst = self.network_ctrl.send_command( "ip a | grep '^[0-9]*:*:'") iface_names_lst = list() iface_id_lst = list() # Get only the wifi interfaces raw_wifi_inface_name_lst = self.network_ctrl.send_command( "iw dev | grep Interface") wifi_iface_name_lst = list() for raw_wifi_iface_name in raw_wifi_inface_name_lst: wifi_iface_name_lst.append( raw_wifi_iface_name.split("Interface ")[1].replace("\n", "")) # transform a line tmp: # '2: enp0s25: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000' # into '2'; 'enp0s25' and lists it. for raw_iface in raw_iface_lst: # Iface Id iface_id = int(raw_iface.split(":")[0]) if iface_id_lst.count(iface_id) == 0: iface_id_lst.append(iface_id) # Iface Name iface_name = raw_iface.split(":")[1].replace(" ", "") if "@" in iface_name: iface_name = iface_name.split("@")[0] if iface_names_lst.count(iface_name) == 0: iface_names_lst.append(iface_name) # Take the information of the interfaces separately for i, iface_id in enumerate(iface_id_lst): iface_name = iface_names_lst[i] interface = NetworkInterface(iface_id, iface_name) raw_iface_info_lst = self.network_ctrl.send_command( "ip addr show " + iface_name) for raw_iface_info in raw_iface_info_lst: # Status raw_status = raw_iface_info.split("state") if len(raw_status) > 1: status = raw_status[1].split(" ")[1] # Status: UP | DOWN | UNKNOWN if status == "UP": interface.status = Status.up elif status == "DOWN": interface.status = Status.down else: interface.status = Status.unknown # MAC raw_mac = raw_iface_info.split("link/ether") if len(raw_mac) > 1: raw_mac = raw_mac[1].split() interface.mac = raw_mac[0] # IP Address raw_ip = raw_iface_info.split("inet") if len(raw_ip) > 1: raw_ip = raw_ip[1].split(" ")[1].split("/") interface.add_ip_address(raw_ip[0], int(raw_ip[1])) # Wifi information if wifi_iface_name_lst.count(iface_name) != 0: interface.wifi_information = self.__get_wifi_information( iface_name) interfaces[iface_name] = interface return interfaces def __get_wifi_information(self, iface_name: str) -> WifiInformation: """ If the given interface name belongs to an wifi interface, there are some more infomations. :param iface_name: Name of the network interface :return: WifiInformation """ wifi_information = WifiInformation() raw_wifi_info_lst = self.network_ctrl.send_command("iw dev") right_iface = False for raw_wifi_info in raw_wifi_info_lst: raw_wifi_info = raw_wifi_info.replace("\n", "") if "Interface" in raw_wifi_info: right_iface = True if iface_name in raw_wifi_info else False elif right_iface: if "wdev" in raw_wifi_info: wifi_information.wdev = raw_wifi_info.split(" ")[1] elif "ssid" in raw_wifi_info: wifi_information.ssid = raw_wifi_info.split(" ")[1] elif "type" in raw_wifi_info: wifi_information.type = raw_wifi_info.split(" ")[1] elif "channel" in raw_wifi_info: wifi_information.channel = int(raw_wifi_info.split(" ")[1]) wifi_information.channel_width = int( raw_wifi_info.split(" ")[5]) wifi_information.channel_center1 = int( raw_wifi_info.split(" ")[8]) return wifi_information def _get_router_cpu_process(self) -> List: """ :return: The cpu processes of the given Router object """ cpu_processes = list() raw_cpu_process_lst = self.network_ctrl.send_command("top -n 1") # A line looks like: # 1051 1020 root R 1388 5% 9% firefox for cpu_process_info_line in raw_cpu_process_lst[4:]: cpu_process_info_lst = cpu_process_info_line.split() if len(cpu_process_info_lst) > 7: # Get the infos pid = int(cpu_process_info_lst[0]) user = cpu_process_info_lst[2] mem = float(cpu_process_info_lst[5].replace("%", "")) cpu = float(cpu_process_info_lst[6].replace("%", "")) command = "" for i in range(7, len(cpu_process_info_lst)): command += cpu_process_info_lst[i] cpu_process = CPUProcess(pid, user, mem, cpu, command) cpu_processes.append(cpu_process) return cpu_processes def _get_router_mem_ram(self) -> RAM: """ :return: The RAM of the given Router. """ ram = None raw_mem_lst = self.network_ctrl.send_command("free -m")[1:] for ram_info_line in raw_mem_lst: if "Mem" in ram_info_line: # Split and remove the spaces ram_info_lst = ram_info_line.split() # Get the infos total = int(ram_info_lst[1]) used = int(ram_info_lst[2]) free = int(ram_info_lst[3]) shared = int(ram_info_lst[4]) buffers = int(ram_info_lst[5]) ram = RAM(total, used, free, shared, buffers) return ram def _get_router_sockets(self) -> List: """ :return: The Sockets of the Router. """ socket_lst = list() raw_socket_lst = self.network_ctrl.send_command("netstat -taupn")[2:] for raw_socket in raw_socket_lst: # raw_socket looks like: # tcp 0 32 192.168.1.1:22 192.168.1.239:51891 ESTABLISHED 1067/dropbear raw_socket = raw_socket.split() socket = InternetSocket() socket.protocol = raw_socket[0] raw_local_address = raw_socket[3].split(":") socket.local_address = raw_local_address[0] if len( raw_local_address) == 2 else "::" socket.local_port = raw_local_address[-1] raw_foreign_address = raw_socket[4].split(":") socket.foreign_address = raw_foreign_address[0] if len( raw_foreign_address) == 2 else "::" socket.foreign_port = raw_foreign_address[-1] raw_process = "-1/error" if raw_socket[0] == "tcp": socket.state = raw_socket[5] raw_process = raw_socket[6].split("/") elif raw_socket[0] == "udp": raw_process = raw_socket[5].split("/") socket.pid = int(raw_process[0]) socket.program_name = raw_process[1] socket_lst.append(socket) return socket_lst