diff --git a/fritzflash.py b/fritzflash.py old mode 100755 new mode 100644 index 4641ec1..c22d227 --- a/fritzflash.py +++ b/fritzflash.py @@ -1,22 +1,20 @@ #! /usr/bin/env python3 import argparse import ipaddress -from ipaddress import ( - IPv4Interface, - IPv4Address, - IPv6Interface, - IPv6Address, - AddressValueError, -) import platform import socket import time +from contextlib import contextmanager from ftplib import FTP +from ipaddress import ( + IPv4Address, + IPv4Interface, + IPv6Address, + IPv6Interface, +) from pathlib import Path from subprocess import run -from contextlib import contextmanager - -from typing import List, ContextManager, Union +from typing import ContextManager, List, Union from simple_tftp import serve_file @@ -52,7 +50,7 @@ def __init__( break except socket.timeout: i += 1 - except OSError as e: + except OSError: time.sleep(1) i += 1 if i > max_retry: @@ -115,8 +113,7 @@ def set_ip(ipinterface: IPInterface, network_device: str) -> ContextManager[None ipinterface.with_prefixlen, "dev", network_device, - ], - capture_output=True, + ] ) else: output = run( @@ -126,7 +123,7 @@ def set_ip(ipinterface: IPInterface, network_device: str) -> ContextManager[None "ipv4", "add", "address", - f'"{network_device}"', + f"{network_device}", f"{ipinterface.ip}", f"{ipinterface.netmask}", ], @@ -143,10 +140,9 @@ def set_ip(ipinterface: IPInterface, network_device: str) -> ContextManager[None "ipv4", "delete", "address", - f'"{network_device}"', + f"{network_device}", f"{ipinterface.ip}", - ], - capture_output=True, + ] ) @@ -203,17 +199,7 @@ def start_message(ip_address): "You can always find the most current version of this script at https://www.github.com/freifunk-darmstadt/fritz-tools\n\n" "It is strongly recommended to only connect your computer to the device you want to flash.\n" "Try to disable all other connections (Ethernet, WiFi/WLAN, VMs) if detection fails.\n" - "Sometimes an unmanaged switch between your AVM device and your computer is helpful.\n\n" - "If you run this program with according permission, it will configure IPs on your host automatically.\n" - "Otherwise, make sure you have assigned your PC a static IP Address in the Subnet of the device you want to flash.\n" - "The following example would be a completely fine option:\n" - ) - print("IP-Address: %s" % str(ipaddress.ip_address(ip_address) + 1)) - print("Subnet: 255.255.255.0") - print("Gateway: %s" % str(ipaddress.ip_address(ip_address))) - print("DNS Servers: Leave blank\n") - print( - "Once you're ready to flash, press enter, disconnect power from your AVM device and reconnect the power-supply." + "Sometimes an unmanaged switch between your AVM device and your computer is helpful." ) @@ -278,7 +264,7 @@ def autodiscover_avm_ip(): bytearray.fromhex("0000120101000000c0a8b20100000000"), ("255.255.255.255", 5035), ) - while 1: + while True: data, addr = receiver.recvfrom(64) if addr[0] == "192.168.178.1": print("\rFritzBox found at %s" % addr[0]) @@ -325,6 +311,9 @@ def determine_image_name(env_string): "gluon": ["avm-fritz-box-7312-sysupgrade.bin"], "openwrt": ["avm_fritz7312-squashfs-sysupgrade.bin"], }, + "193": { + "openwrt": ["avm_fritz3390-squashfs-sysupgrade.bin"], + }, "196": { "gluon": ["avm-fritz-box-7360-v2-sysupgrade.bin"], "openwrt": ["avm_fritz7360sl-squashfs-sysupgrade.bin"], @@ -345,9 +334,7 @@ def determine_image_name(env_string): "openwrt": ["avm_fritzbox-4040-squashfs-eva.bin"], }, "203": { - "openwrt": [ - "openwrt-lantiq-xrx200-avm_fritz7362sl-initramfs-kernel.bin" - ] + "openwrt": ["openwrt-lantiq-xrx200-avm_fritz7362sl-initramfs-kernel.bin"] }, "209": { "openwrt": ["openwrt-lantiq-xrx200-avm_fritz7412-initramfs-kernel.bin"] @@ -566,9 +553,6 @@ def perform_tftp_flash(initramfsfile: Path, sysupgradefile: Path): parser = argparse.ArgumentParser( description="Flash Gluon image to AVM devices using EVA or/and TFTP." ) - parser.add_argument( - "--ip", type=str, help="IP Address of device. Autodiscovery if not specified." - ) parser.add_argument( "--image", type=str, @@ -606,32 +590,38 @@ def perform_tftp_flash(initramfsfile: Path, sysupgradefile: Path): flash_tftp = input().lower().startswith("y") start_message("192.168.178.1") - input() - with set_ip(ipaddress.ip_interface("192.168.178.2/24"), args.device) as can_set_ip: + client_intf = ipaddress.ip_interface("192.168.178.2/24") + with set_ip(client_intf, args.device) as can_set_ip: if can_set_ip: - print("did set ip to 192.168.178.2/24") + print(f"did set ip to {client_intf}") else: - print("could not set ip to 192.168.178.2/24") + print(f"could not set ip to {client_intf}") + print( + "If you run this program with according permission, it will configure IPs on your host automatically.\n" + "Otherwise, make sure you have assigned your PC a static IP Address in the Subnet of the device you want to flash.\n" + "The following example would be a completely fine option:\n" + ) + print(f"IP-Address: {client_intf.ip}") + print(f"Subnet: {client_intf.netmask}") + print("Gateway: 192.168.178.1") + print("DNS Servers: Leave blank\n") + print( + "Once you're ready to flash, press enter, disconnect power from your AVM device and reconnect the power-supply." + ) + input() - if args.ip: - try: - ip = ipaddress.ip_address(args.ip) - except AddressValueError: - print(f"{args.ip} is not a valid IPv4 address!") - exit(1) - else: - print("Trying to autodiscover! Abort via Ctrl-c.") - ip = autodiscover_avm_ip() + print("Trying to autodiscover! Abort via Ctrl-c.") + ip = autodiscover_avm_ip() - if ip is None: - print("\nAutodiscovery failed!") - print("Press any key to exit.") - input() - exit(1) + if ip is None: + print("\nAutodiscovery failed!") + print("Press any key to exit.") + input() + exit(1) - print("\nAutodiscovery succesful!") - print(f"-> Device detected at {ip}.") + print("\nAutodiscovery succesful!") + print(f"-> Device detected at {ip}.") if args.image is None: # Try to automatically locate an image to use @@ -664,4 +654,4 @@ def perform_tftp_flash(initramfsfile: Path, sysupgradefile: Path): time.sleep(30) perform_bootloader_flash(sysupgradefile, imagefile, flash_tftp) print("Finished flash procedure") - finish_message() \ No newline at end of file + finish_message() diff --git a/simple_tftp.py b/simple_tftp.py index b487d0a..c658cd6 100644 --- a/simple_tftp.py +++ b/simple_tftp.py @@ -1,8 +1,10 @@ -import os.path, random, sys -from socket import socket, AF_INET, AF_INET6, SOCK_DGRAM, timeout -from pathlib import Path +#! /usr/bin/env python3 +import random +import sys from contextlib import contextmanager -from typing import Tuple, Generator, Literal +from pathlib import Path +from socket import AF_INET, SOCK_DGRAM, socket, timeout +from typing import Generator, Literal, Tuple UDP_IP = "0.0.0.0" UDP_PORT = 69 # TFTP Protocol Port (69) @@ -160,7 +162,7 @@ def serve(port: int, file: Path, mode: TRANSFER_MODES_T) -> Tuple[bool, str]: return True, addr block += 1 if block % 256 == 0: - print(f"{block} / {size}") + print(f"{block} / {size}", end="") packet = create_data_packet(block, file, mode) sock.sendto(packet, addr) @@ -212,7 +214,7 @@ def serve_file( yield serve(port, file, mode) -if __name__ == "__main__": +def main_tftp(): for success, host in serve_file(sys.argv[1]): if success: print(f"Successfully served file {sys.argv[1]} to Host {host}") @@ -220,7 +222,7 @@ def serve_file( input( "Press any key to serve to another Host, CTRL-c or CTRL-d to stop TFTP server." ) - except (KeyboardInterrupt, EOFError) as interrupt: + except (KeyboardInterrupt, EOFError): break else: print(f"Timeout serving file to Host {host}")