#!/usr/bin/env python3 import functools import json import socket import sys ''' Takes as input a list of domain names to test. Return wether they are IPv4/IPv6-compatible. Usage: > cat test.txt baionet.fr google.com > cat test.txt | ./dns-sacha.py | jq [ { "host": "baionet.fr", "v4": true, "v6": false }, { "host": "google.com", "v4": true, "v6": true } ] ''' class UrlIp: ''' Struct wrapping a single record entry. Does it have IPv4 support? IPv6 support? ''' def __init__(self, host, v4, v6): self.host = host self.v4 = v4 self.v6 = v6 def get_host_records(host): ''' Folds all the DNS entries of a Host and looks whether or not we can find v4 and v6 records. reduce == left fold in the python world btw... ''' records = socket.getaddrinfo(host, 80) return(functools.reduce(_test_record,records,UrlIp(host,False,False))) def _test_record(urlip, rec): ''' Fold function for get_host_records. Too big for a lambda not to get messy. Gotta love Python... ''' (family, _rtype, proto, _canonname, _sockaddr) = rec if family == socket.AF_INET: urlip.v4 = True elif family == socket.AF_INET6: urlip.v6 = True return urlip def parse_hosts(file_name): with open(file_name, 'r') as f: return f.readlines() def render_results(results): ''' Takes an array of UrlIp and renders that to json. Python's json.dumps only works with dictionnaries, not classes. Extracting the dictionnary representation of the class. ''' return(json.dumps([r.__dict__ for r in results])) if __name__ == '__main__': entries = [l.strip() for l in sys.stdin.readlines()] test_results = [get_host_records(entry) for entry in entries] print(render_results(test_results))