-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlookup.py
executable file
·138 lines (107 loc) · 3.62 KB
/
lookup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import threading, io, sys, socket, math
from main import get_logger
THREAD_NUM = 200
PRINT_FREQ = 10
def load_host_list(filename):
"""Loads the list of hosts to test, looking up the missing parts.
The file should have each host on its own line,
in the form of "hostname IP", with at least one of those present.
Lines that do not conform are ignored.
"""
try:
input_file = open(filename, "r")
lines = [l.strip().split() for l in input_file.readlines()]
input_file.close()
except IOError:
print("Error: could not read in file!", file=sys.stderr)
sys.exit(-1)
hosts = [tuple(l) for l in lines if len(l)==2] # complete records
rest = [l[0] for l in lines if len(l)==1] # incomplete records
IPs = [x for x in rest if is_valid_IP(x)]
names = list(set(rest)-set(IPs))
# divide the arrays between threads...
thread_ips = divide_array(IPs, THREAD_NUM)
thread_names = divide_array(names, THREAD_NUM)
# ...and look them up in parallel
log.info("Looking up the missing values...")
threads = []
counter = IntWrapper(initial_value=0, total=len(IPs)+len(rest))
for i in range(THREAD_NUM):
thread = threading.Thread(
target=DNS_lookup,
args=(thread_ips[i], thread_names[i], hosts, counter)
)
thread.start()
threads.append(thread)
for thread in threads:
thread.join()
return hosts
# the thread for (reverse) DNS lookup
def DNS_lookup(IPs, hostnames, hosts, counter):
for ip in IPs:
host = (lookup_host_name(ip), ip)
hosts.append(host)
counter.inc()
for name in hostnames:
addr = lookup_host_addr(name)
# if we can't find the IP, we ignore the record
if addr:
hosts.append((name, addr))
counter.inc()
class IntWrapper:
"""A threadsafe wrapper for an integer, for use as a counter."""
def __init__(self, initial_value=0, total=0):
self.value = initial_value
self.total = total
self.lock = threading.Lock()
def inc(self):
self.lock.acquire()
self.value += 1
if (self.value % PRINT_FREQ == 0 or self.value == self.total):
log.info("\t%d/%d" % (self.value, self.total))
self.lock.release()
###
#
# Helper functions
#
###
def is_valid_IP(IP):
"""Returns True if the given IP is in the form '255.255.255.255'"""
try:
socket.inet_aton(IP)
return IP.count(".") == 3
except OSError:
return False
def lookup_host_name(IP):
"""Looks up the host name, or a "?" if no hostname can be found."""
try:
return socket.gethostbyaddr(IP)[0]
except socket.herror:
return "?"
def lookup_host_addr(hostname):
"""Looks up a single host IP address.
Returns None if it cannot find one."""
try:
return socket.gethostbyname(hostname)
except socket.gaierror:
return None
def divide_array(array, num):
"""Divides the given array into num disjoint ones."""
ret = []
for i in range(num):
N = math.ceil(len(array)/num)
ret.append( array[i*N : (i+1)*N] )
return ret
########################################################################
if __name__=="__main__":
log = get_logger("main")
if len(sys.argv) != 2:
print("Usage: "+sys.argv[0]+" host_list")
sys.exit(0)
log.info("Reading in the host list...")
# read in the file to process
host_list = load_host_list(sys.argv[1])
for hostname, ip in host_list:
print(hostname+" "+ip)