From 71f9bf51a250005d90e3e681ba92c6c7a9b5fb18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juhani=20Krekel=C3=A4?= Date: Wed, 29 Aug 2018 20:36:46 +0300 Subject: [PATCH] Correctly recognize IPv6 addresses --- src/process_known_hosts.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/process_known_hosts.py b/src/process_known_hosts.py index 0472900..ebe9a7b 100644 --- a/src/process_known_hosts.py +++ b/src/process_known_hosts.py @@ -44,9 +44,33 @@ def is_ip(domain): # The fields are in the range 0…255 return all(0 <= field <= 266 for field in fields_num) + def is_hexdigit(c): + return ord('0') <= ord(c) <= ord('9') or ord('a') <= ord(c) <= ord('f') or ord('A') <= ord(c) <= ord('F') + def is_ipv6(domain): - # TODO: Implement this - return False # FIXME: This is wrong + # An IPv6 address is represented by 8 groups of 16-bit + # numbers expressed in hex. They can be either fixed-width + # or have their leading zeroes removed. A run of zeroes + # can be abreviated with ::, but only once per address + + # If we have two or more doublecolons, it's not valid + # If we have one, we can have anywhere between 3 to 8 + # "fields" separated by ':' + # If we have zero, we must have exactly 8 fields + doublecolons = domain.count('::') + if doublecolons > 1: + return False + else: + fields = domain.split(':') + if doublecolons == 1 and len(fields) > 8: + return False + elif doublecolons == 0 and len(fields) != 8: + return False + + # All of the "fields" must have 0 to 4 hex digits + if not all(0 <= len(field) <= 4 for field in fields): + return False + return all(all(map(is_hexdigit, field)) for field in fields) return is_ipv4(domain) or is_ipv6(domain)