Browse Source

Update from Talos

Graham Northup 2 months ago
  1. 75


@ -27,22 +27,25 @@ RECPAT = re.compile(r'''
''', re.X)
class Record(object):
__slots__ = ['name', 'cls', 'tp', 'value']
__slots__ = ['file', 'line', 'name', 'cls', 'tp', 'value']
def __init__(self, name, cls, tp, value):
def __init__(self, file, line, name, cls, tp, value):
self.file = file
self.line = line = name
self.cls = cls = tp
self.value = value
def from_match(cls, match):
def from_match(cls, file, line, match):
return cls(
file, line,
*'name', 'class', 'type', 'value')
def __repr__(self):
return f'Record(name={!r}, cls={self.cls!r}, tp={!r}, value={self.value!r})'
return f'Record(file={self.file!r}, line={self.line!r}, name={!r}, cls={self.cls!r}, tp={!r}, value={self.value!r})'
def __hash__(self):
return hash((, self.cls,, self.value))
@ -52,17 +55,23 @@ class Record(object):
return False
return (, self.cls,, self.value) == (, other.cls,, other.value)
def loc(self):
return f'{self.file}:{self.line}'
FWD = {} # zonefile -> [record]
RVS = {} # id
def get_recs_from_file(f):
rv = []
for line in open(fn):
for lno, line in enumerate(open(fn)):
line = line.partition(';')[0].strip()
if not line:
match = RECPAT.match(line)
if not match:
print(f'rejected line: {line!r}')
#print(f'rejected line: {line!r}')
rec = Record.from_match(match)
rec = Record.from_match(fn, lno + 1, match)
return rv
@ -108,53 +117,79 @@ for fn, zone in ORIGINS.items():
for fn, rv in REVERSE.items():
RVS[fn] = get_recs_from_file(open(fn))
print('\n# Comparisons')
for za in ORIGINS.keys():
for zb in ORIGINS.keys():
if za <= zb:
print('Comparison between', za, 'and', zb)
print(f'\n## Comparison between `{za}` and `{zb}`')
sa = set(FWD[za])
sb = set(FWD[zb])
ma = sb - sa
mb = sa - sb
print(f'Missing from {za}:')
print(f'\nMissing from `{za}`:\n')
for i in ma:
print('\t', i)
print(f'Missing from {zb}:')
print(f'- `{i}`')
print(f'\nMissing from `{zb}`:\n')
for i in mb:
print('\t', i)
print(f'- `{i}`')
mrvs = {} # canonaddr -> rec
seen_addrs = {} # addr -> oldname
seen_names = {} # name -> firstaddr
seen_addrs_cls = {'A': {}, 'AAAA': {}} # class -> addr -> oldname
seen_names_cls = {'A': {}, 'AAAA': {}} # name -> firstaddr
for z in ORIGINS.keys():
for rec in FWD[z]:
if == 'A':
mrvs[rec.value] = rec
elif == 'AAAA':
mrvs[canon_ip6(into_digits(expand_ip6(rec.value)))] = rec
print('Reverse records:')
print('\n# Reverse records')
for r, addr in REVERSE.items():
cls = 'AAAA' if ':' in addr else 'A'
seen_addrs = seen_addrs_cls[cls]
seen_names = seen_names_cls[cls]
for rec in RVS[r]:
if != 'PTR':
a = cons_addr(rec, addr)
if a in seen_addrs:
print(f'\t- Rvs {a} (for {rec.value}) has already been seen as {seen_addrs[a]}')
print(f'- `{rec.loc()}`: Rvs `{a}` (for `{rec.value}`) has already been seen as `{seen_addrs[a]}`')
del mrvs[a]
except KeyError:
print(f'\t- Rvs {a} (supposedly {rec.value}) doesn\'t correspond to any forward record')
print(f'- `{rec.loc()}`: Rvs `{a}` (supposedly `{rec.value}`) doesn\'t correspond to any forward record')
seen_addrs[a] = rec.value
if rec.value in seen_names:
print(f'\t- Name {rec.value} (for {a}) has already been seen as {seen_names[rec.value]}')
if a == seen_names[rec.value]:
print(f'- `{rec.loc()}`: Redundant record for `{rec.value}` to `{a}`')
print(f'- `{rec.loc()}`: Name `{rec.value}` (for `{a}`) has already been seen as `{seen_names[rec.value]}`')
seen_names[rec.value] = a
for addr, rec in mrvs.items():
print(f'\t- No rvs for {addr} (in {rec!r})')
print(f'- `{rec.loc()}`: No rvs for `{addr}` (`{}.{ORIGINS[rec.file]}`)')
mfwd = {'A': {}, 'AAAA': {}} # class -> nm -> (addr, rec)
for z in ORIGINS.keys():
for rec in FWD[z]:
if == 'A':
mfwd[][ + '.' + ORIGINS[z]] = (rec.value, rec)
elif == 'AAAA':
mfwd[][ + '.' + ORIGINS[z]] = (canon_ip6(into_digits(expand_ip6(rec.value))), rec)
print('\n# V4/V6')
names_v4 = set(mfwd['A'].keys())
names_v6 = set(mfwd['AAAA'].keys())
print('\n## Names not yet added to IPv6')
for nm in names_v4 - names_v6:
print(f'- `{nm}` (at `{mfwd["A"][nm][0]}`)')
print('\n## Names exclusive to IPv6')
for nm in names_v6 - names_v4:
print(f'- `{nm}` (at `{mfwd["AAAA"][nm][0]}`)')
print('\n## Names in both')
for nm in names_v4 & names_v6:
print(f'- `{nm}` (at `{mfwd["A"][nm][0]}` and `{mfwd["AAAA"][nm][0]}`)')
#for fn, recs in FWD.items():
# for rec in recs: