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
26 # XXX TODO: Set the user agent and allow the use of a proxy
27 # Set up a proper Request object, set the user agent and if desired, a proxy
28 def fetch_delegation(delegation_url
):
29 """ Fetch (with progress meter) and return the contents of a delegation. """
30 rows
, columns
= os
.popen('stty size', 'r').read().split()
31 fetcher
= urllib2
.urlopen(delegation_url
)
32 length
= int(fetcher
.headers
.get("content-length"))
34 raise Exception("Missing content-length header in reply from server.")
35 print "Fetching " + str(length
) + " bytes"
36 chunk
= int(int(length
)/(int(columns
) -4))
39 # XXX TODO: we need to redraw the screen entirely, each run
40 # XXX TODO: Currently, if the user changes the screen, we draw incorrectly
41 sys
.stdout
.write("[" + "." * (int(columns
) - 2) + "]")
43 sys
.stdout
.write('\b' * (int(columns
) - 2))
45 page
+= fetcher
.read(chunk
)
47 sys
.stdout
.write('\b')
52 sys
.stdout
.write('\n')
55 if length
== len(page
):
58 raise Exception("Error fetching the right number of bytes!")
60 def cache_delegation(delegation_url
, cache_dir
):
61 """ Attempt to cache the contents of a delegation url in our cache dir. """
66 print "Initializing the cache directory..."
70 print "Unable to initialize cache directory. Sorry!"
73 print "Fetching " + delegation_url
74 delegation
= fetch_delegation(delegation_url
)
75 tmp
= delegation_url
.split('/')
76 delegation_file
= str(cache_dir
) + str(tmp
[-1])
77 f
= open(delegation_file
, 'w')
82 print "Unable to fetch or cache delegation"
85 def cache_age_check(cache_dir
, cached_files
):
86 """ Returns True if the mtime of any files in cache dir is > 24hrs."""
90 print "Did you initialize the cache directory?"
92 for file in cached_files
.split(","):
93 fstat
= os
.stat(cache_dir
+ file)
94 if (time
.time() - fstat
.st_mtime
) > 86400:
98 def update_delegation_cache(delegation_urls
, cache_dir
):
99 """ Fetch multiple delegation urls and cache the contents. """
100 print "Updating delegation cache"
101 for url
in delegation_urls
.split():
103 cache_delegation(url
, cache_dir
)
105 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 os
.stat(delegation_file
)
112 f
= open(delegation_file
, "r")
113 delegations
= [ dict((k
,v
) for k
,v
in zip(keys
.split(","), line
.split("|")))
114 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: \n" + delegation_urls
124 for url
in delegation_urls
.split():
125 filename
= url
.rpartition('/')
127 print "Attempting to load delegation file: " + filename
[-1]
128 delegations
.append(load_delegation(cache_dir
+ filename
[-1]))
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. 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
:
179 cache_dir
= str(os
.path
.expanduser('~')) + "/.blockfinder/"
180 update_delegations
= False
182 ftp://ftp.arin.net/pub/stats/arin/delegated-arin-latest
183 ftp://ftp.ripe.net/ripe/stats/delegated-ripencc-latest
184 ftp://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-latest
185 ftp://ftp.apnic.net/pub/stats/apnic/delegated-apnic-latest
186 ftp://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-latest
189 for url
in delegation_urls
.split():
190 filename
= url
.rpartition('/')
191 delegation_files
+= filename
[-1] + ","
192 delegation_fmt
="rir,cc,type,n,nn,asn,status"
193 iso_codes
="http://www.iso.org/iso/list-en1-semic-3.txt"
194 user_agent
= "blockfinder"
195 update_delegations
= False
201 elif o
in ("-h", "--help"):
204 elif o
in ("-c", "--cachedir"):
206 elif o
in ("-u", "--useragent"):
208 elif o
in ("-p", "--progress"):
210 elif o
in ("-s", "--silent"):
212 elif o
in ("-o", "--output"):
214 elif o
in ("-4", "--ipv4"):
215 requests
.append("ipv4")
216 elif o
in ("-6", "--ipv6"):
217 requests
.append("ipv6")
218 elif o
in ("-a", "--asn"):
219 requests
.append("asn")
220 # XXX TODO: This should be a positional argument as it's the only manditory one...
221 elif o
in ("-t", "--nation-state"):
223 elif o
in ("-i", "--initialize-delegations"):
224 update_delegations
= True
226 assert False, "Unhandled option; Sorry!"
228 # Update and quit of requested
229 if update_delegations
:
230 update_delegation_cache(delegation_urls
, cache_dir
)
233 print "Nothing to do. Have you requested anything?"
234 print "Example usage: blockfinder -v --ipv4 -t mm"
236 # Check our cache age and warn if it's aged
237 total_delegations
= 0
238 if cache_age_check(cache_dir
, delegation_files
) and verbose
:
239 print "Your delegation cache is older than 24 hours; you probably want to update it."
240 delegations
= load_all_delegations(cache_dir
, delegation_urls
)
241 for delegation
in delegations
:
242 total_delegations
+= len(delegation
)
244 print "We have %d entries in our delegation cache." % total_delegations
248 for delegation
in delegations
:
250 results
= lookup_country(country
, delegation
)
251 resultnum
+= len(results
)
252 for result
in results
:
253 for request
in requests
:
254 if result
['type'] == request
:
261 print "We found approx possible %d entries in our delegation cache." % resultnum
262 print "We found %d matching entries in our delegation cache." % matchnum
264 if __name__
== "__main__":