2 # -*- coding: utf-8 -*-
4 # For the people of Smubworld!
12 __program__
= 'blockfinder'
13 __url__
= 'http://github.com/ioerror/blockfinder/'
14 __author__
= 'Jacob Appelbaum <jacob@appelbaum.net>'
15 __copyright__
= 'Copyright (c) 2009'
16 __license__
= 'See LICENSE for licensing information'
20 from future
import antigravity
24 # XXX TODO: Set the user agent and allow the use of a proxy
25 # Set up a proper Request object, set the user agent and if desired, a proxy
26 def fetch_delegation(delegation_url
):
27 """ Fetch (with progress meter) and return the contents of a delegation. """
28 rows
, columns
= os
.popen('stty size', 'r').read().split()
29 fetcher
= urllib2
.urlopen(delegation_url
)
30 length
= int(fetcher
.headers
.get("content-length"))
32 raise Exception("Missing content-length header in reply from server.")
33 print "Fetching " + str(length
) + " bytes"
34 chunk
= int(int(length
)/(int(columns
) -4))
37 # XXX TODO: we need to redraw the screen entirely, each run
38 # XXX TODO: Currently, if the user changes the screen, we draw incorrectly
39 sys
.stdout
.write("[" + "." * (int(columns
) - 2) + "]")
41 sys
.stdout
.write('\b' * (int(columns
) - 2))
43 page
+= fetcher
.read(chunk
)
45 sys
.stdout
.write('\b')
50 sys
.stdout
.write('\n')
53 if length
== len(page
):
56 raise Exception("Error fetching the right number of bytes!")
58 def cache_delegation(delegation_url
, cache_dir
):
59 """ Attempt to cache the contents of a delegation url in our cache dir. """
64 print "Initializing the cache directory..."
68 print "Unable to initialize cache directory. Sorry!"
71 print "Fetching " + delegation_url
72 delegation
= fetch_delegation(delegation_url
)
73 tmp
= delegation_url
.split('/')
74 delegation_file
= str(cache_dir
) + str(tmp
[-1])
75 f
= open(delegation_file
, 'w')
80 print "Unable to fetch or cache delegation"
83 def cache_is_dated(cache_dir
, cached_files
):
84 """ Returns True if the mtime of any files in cache dir is > 24hrs."""
88 print "Did you initialize the cache directory?"
90 for file in cached_files
.split(","):
91 fstat
= os
.stat(cache_dir
+ file)
92 if (time
.time() - fstat
.st_mtime
) > 86400:
96 def update_delegation_cache(cache_dir
, delegation_urls
):
97 """ Fetch multiple delegation urls and cache the contents. """
98 print "Updating delegation cache..."
99 for url
in delegation_urls
.split():
101 cache_delegation(url
, cache_dir
)
104 print "Unable to update delegation for " + url
107 def load_delegation(delegation_file
):
108 """ Load, parse and store the delegation file contents as a list. """
109 keys
= "rir,cc,type,n,nn,asn,status"
111 f
= open(delegation_file
, "r")
112 delegations
= [ dict((k
,v
) for k
,v
in zip(keys
.split(","), line
.split("|")))
113 for line
in f
.readlines() if not line
.startswith("#")]
117 print "It appears that we are missing " + delegation_file
119 def load_all_delegations(cache_dir
, delegation_urls
):
120 """ Load all delegations into memory. """
123 print "Attempting to load the following urls: " + delegation_urls
124 for url
in delegation_urls
.split():
125 filename
= url
.rpartition('/')[-1]
127 print "Attempting to load delegation file: " + filename
128 delegations
.append(load_delegation(cache_dir
+ filename
))
131 def lookup_country(cc
, delegation
):
132 """ Return data about a given county code in a supplied delegation. """
133 return [d
for d
in delegation
if d
['cc'] == cc
]
135 def lookup_type(type, delegation
):
136 """ Return data about a given type in a supplied delegation. """
137 return [d
for d
in delegation
if d
['type'] == type]
140 """ Print usage information. """
141 print >> sys
.stderr
, """
142 blockfinder [-c DIR] -i
143 blockfinder [options] -t COUNTRY
145 The first form initializes the local cache. The second form queries it.
147 Understood options (not all of which are implemented yet):
148 -h, --help Show this help and exit
150 -c, --cachedir DIR Set the cache directory
154 -4, --ipv4 Search IPv4 allocations
155 -6, --ipv6 Search IPv6 allocation
156 -a, --asn Search ASN allocations
157 -t, --nationstate CC Set the country to search (given as a two-letter code)
159 At least one of -t or -i is required, and when in -t mode, at least one of -4,
160 -6, and -a is required in order to do anything sensible.
164 """ Where the magic starts. """
166 opts
, args
= getopt
.getopt(sys
.argv
[1:],
168 ["verbose", "help", "cachedir=", "useragent=", "progress",
169 "silent", "output=", "ipv4", "ipv6", "asn", "country=",
170 "initialize-delegation"])
171 except getopt
.GetoptError
, err
:
180 cache_dir
= str(os
.path
.expanduser('~')) + "/.blockfinder/"
181 update_delegations
= False
183 ftp://ftp.arin.net/pub/stats/arin/delegated-arin-latest
184 ftp://ftp.ripe.net/ripe/stats/delegated-ripencc-latest
185 ftp://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-latest
186 ftp://ftp.apnic.net/pub/stats/apnic/delegated-apnic-latest
187 ftp://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-latest
190 for url
in delegation_urls
.split():
191 filename
= url
.rpartition('/')
192 delegation_files
+= filename
[-1] + ","
193 update_delegations
= False
199 elif o
in ("-h", "--help"):
202 elif o
in ("-c", "--cachedir"):
204 elif o
in ("-u", "--useragent"):
206 elif o
in ("-p", "--progress"):
208 elif o
in ("-s", "--silent"):
210 elif o
in ("-o", "--output"):
212 elif o
in ("-4", "--ipv4"):
213 requests
.append("ipv4")
214 elif o
in ("-6", "--ipv6"):
215 requests
.append("ipv6")
216 elif o
in ("-a", "--asn"):
217 requests
.append("asn")
218 # XXX TODO: This should be a positional argument as it's the only manditory one...
219 elif o
in ("-t", "--nation-state"):
221 elif o
in ("-i", "--initialize-delegations"):
222 update_delegations
= True
224 assert False, "Unhandled option; Sorry!"
226 # Update and quit of requested
227 if update_delegations
:
228 update_delegation_cache(cache_dir
, delegation_urls
)
231 print "Nothing to do. Have you requested anything?"
232 print "Example usage: blockfinder -v --ipv4 -t mm"
234 # Check our cache age and warn if it's aged
235 total_delegations
= 0
236 if cache_is_dated(cache_dir
, delegation_files
) and verbose
:
237 print "Your delegation cache is older than 24 hours; you probably want to update it."
238 delegations
= load_all_delegations(cache_dir
, delegation_urls
)
239 for delegation
in delegations
:
240 total_delegations
+= len(delegation
)
242 print "We have %d entries in our delegation cache." % total_delegations
246 for delegation
in delegations
:
248 results
= lookup_country(country
, delegation
)
249 resultnum
+= len(results
)
250 for result
in results
:
251 for request
in requests
:
252 if result
['type'] == request
:
259 print "We found approx possible %d entries in our delegation cache." % resultnum
260 print "We found %d matching entries in our delegation cache." % matchnum
262 if __name__
== "__main__":