1# -----------------------------------------------------------------------------
2# Copyright (c) 2008 by David P. D. Moss. All rights reserved.
3#
4# Released under the BSD license. See the LICENSE file for details.
5# -----------------------------------------------------------------------------
6"""A basic implementation of RFC 1924 ;-)"""
7
8from netaddr.core import AddrFormatError
9from netaddr.ip import IPAddress
10
11
12def chr_range(low, high):
13 """Returns all characters between low and high chars."""
14 return [chr(i) for i in range(ord(low), ord(high) + 1)]
15
16
17#: Base 85 integer index to character lookup table.
18BASE_85 = (
19 chr_range('0', '9')
20 + chr_range('A', 'Z')
21 + chr_range('a', 'z')
22 + [
23 '!',
24 '#',
25 '$',
26 '%',
27 '&',
28 '(',
29 ')',
30 '*',
31 '+',
32 '-',
33 ';',
34 '<',
35 '=',
36 '>',
37 '?',
38 '@',
39 '^',
40 '_',
41 '`',
42 '{',
43 '|',
44 '}',
45 '~',
46 ]
47)
48
49#: Base 85 digit to integer lookup table.
50BASE_85_DICT = dict(zip(BASE_85, range(0, 86)))
51
52
53def ipv6_to_base85(addr):
54 """Convert a regular IPv6 address to base 85."""
55 ip = IPAddress(addr)
56 int_val = int(ip)
57
58 remainder = []
59 while int_val > 0:
60 remainder.append(int_val % 85)
61 int_val //= 85
62
63 encoded = ''.join([BASE_85[w] for w in reversed(remainder)])
64 leading_zeroes = (20 - len(encoded)) * '0'
65 return leading_zeroes + encoded
66
67
68def base85_to_ipv6(addr):
69 """
70 Convert a base 85 IPv6 address to its hexadecimal format.
71 """
72 tokens = list(addr)
73
74 if len(tokens) != 20:
75 raise AddrFormatError('Invalid base 85 IPv6 address: %r' % (addr,))
76
77 result = 0
78 for i, num in enumerate(reversed(tokens)):
79 num = BASE_85_DICT[num]
80 result += num * 85**i
81
82 ip = IPAddress(result, 6)
83
84 return str(ip)