├── .coveragerc
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── TODO.md
├── appconfig.cfg.dist
├── data
├── rfc-managed.txt
├── ripe-managed-space.txt
└── schema.sql
├── db
├── README
├── bootstrap
├── create_bgp
├── create_irr_as_sets
├── create_irr_routes
├── create_managed
├── create_serials
├── create_source
├── fetch
├── refresh
├── refresh_ripe_managed
└── sources.py
├── docs
└── irrexplorer-logo.png
├── exabgp.conf
├── fetch_ripe_managed.py
├── irrexplorer
├── __init__.py
├── bgpupdate.py
├── irrparser.py
├── irrtest.data
├── irrupdate.py
├── nrtm.py
├── report.py
├── sqldb.py
├── utils.py
└── www.py
├── irrexplorer_config.yml.dist
├── irrexwww
├── query
├── requirements.txt
├── setup.cfg
├── setup.py
├── static
├── img
│ ├── false.png
│ ├── loading.gif
│ └── true.png
├── js
│ └── table.js
└── robots.txt
├── templates
├── index.html
└── search.html
├── tests
├── REGRESSION.CURRENTSERIAL
├── irrtest.data
├── nrtm_server.py
├── nrtm_test.yml
├── test_nrtmclient.py
├── test_regression.py
└── test_utils.py
└── worker
/.coveragerc:
--------------------------------------------------------------------------------
1 | # .coveragerc to control coverage.py
2 | [run]
3 | branch = True
4 | source = .
5 |
6 | [report]
7 | omit =
8 | setup.py
9 | irrexplorer/__init__.py
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | .eggs/
3 | irrexplorer.egg-info/
4 | .coverage
5 | .venv/
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 |
3 | python:
4 | - '2.7'
5 |
6 | install:
7 | - pip install coveralls
8 | - pip install -r requirements.txt
9 | - sudo cp tests/nrtm_test.yml irrexplorer_config.yml
10 | - python setup.py install
11 | # - sudo ip addr add 127.0.0.2/8 dev lo
12 | # - sudo env exabgp.tcp.bind="127.0.0.2" exabgp.tcp.port=179 exabgp.daemon.daemonize=true exabgp tests/bgp_injector.conf
13 | - python tests/nrtm_server.py &
14 |
15 | script:
16 | - python setup.py nosetests
17 |
18 | after_success:
19 | - coveralls
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015, Job Snijders, Peter van Dijk
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | 1. Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | 2. Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | IRR Explorer
2 | ============
3 |
4 | [](https://travis-ci.org/job/irrexplorer)
5 | [](https://coveralls.io/r/job/irrexplorer?branch=master)
6 |
7 | Note: IRR Explorer v2
8 | =====================
9 |
10 | The NLNOG Foundation supported by RIPE NCC commissioned a complete rewrite of IRR Explorer: https://github.com/dashcare/irrexplorer
11 |
12 | This v1 repository has been archived.
13 |
14 | Explore IRR & BGP data in near real time
15 | ----------------------------------------
16 |
17 |
18 |
19 |
20 |
21 | Background
22 | ----------
23 |
24 | IRR Explorer was written to make it easier to debug data in the IRR
25 | system. An example is to verify whether you would be impacted by deployment
26 | if filtering strategies such as "IRR Lockdown".
27 |
28 | video: https://ripe70.ripe.net/archives/video/21/
29 | pdf: https://ripe70.ripe.net/presentations/52-RIPE70_jobsnijders_irrlockdown.pdf
30 |
31 |
32 | Setup
33 | -----
34 |
35 | Copy irrexplorer_config.yml.dist to irrexplorer_config.yml and edit it to your
36 | liking.
37 |
38 | Note that mirroring of many IRR databases is not possible without getting
39 | access granted.
40 |
41 | ```
42 | ( cd db ; ./bootstrap )
43 | ```
44 | This will download IRR database snapshots and setup the database. It will take some time.
45 |
46 | Continously updating BGP and IRR sources:
47 | ```
48 | ./worker
49 | ```
50 |
51 | Finally start the web interface
52 | ```
53 | ./irexwww
54 | ```
55 |
56 | There is query tool as well:
57 | ```
58 | ./query 1.2.3.0/24
59 | ```
60 | It is rather basic and need some work though.
61 |
62 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | IRR Explorer
2 | ============
3 |
4 | # TODO
5 |
6 | * exabgp
7 | * launch
8 | * feed it config
9 | * catch STDOUT from the 'run' process
10 |
11 | * Investigate issue with records going missing
12 | * Logging added, so debugging can actually be done
13 |
14 | * Database
15 | * Upgrade to PostgreSQL 9.5.
16 | * Has better query planner for gin indexes
17 | * Supports ON CONFLICT (UPSERT) which will save us trouble on mirror updates
18 |
19 |
20 |
--------------------------------------------------------------------------------
/appconfig.cfg.dist:
--------------------------------------------------------------------------------
1 | # set this key to something random generated, flask need this
2 | # SECRET_KEY='ssshhh... I'm hunting rabbits'
3 |
--------------------------------------------------------------------------------
/data/rfc-managed.txt:
--------------------------------------------------------------------------------
1 | 0.0.0.0/8 RFC1122
2 | 10.0.0.0/8 RFC1918
3 | 100.64.0.0/10 RFC6598
4 | 127.0.0.0/8 LOOPBACK
5 | 172.16.0.0/12 RFC1918
6 | 192.0.0.0/24 RFC5736
7 | 192.168.0.0/16 RFC1918
8 | 169.254.0.0/16 RFC3927
9 | 192.0.2.0/24 RFC5737
10 | 198.18.0.0/15 RFC2544
11 | 198.51.100.0/24 RFC5737
12 | 203.0.113.0/24 RFC5737
13 | 240.0.0.0/4 CLASS-E
14 | ::ffff:0:0/96 IPv4-mapped
15 | ::/96 IPv4-compatible
16 | fc00::/7 IPv6-ULA
17 |
--------------------------------------------------------------------------------
/data/ripe-managed-space.txt:
--------------------------------------------------------------------------------
1 | 2.0.0.0/8
2 | 5.0.0.0/8
3 | 24.132.0.0/14
4 | 25.0.0.0/8
5 | 31.0.0.0/8
6 | 37.0.0.0/8
7 | 45.128.0.0/11
8 | 45.8.0.0/13
9 | 45.80.0.0/12
10 | 46.0.0.0/8
11 | 51.0.0.0/8
12 | 53.0.0.0/8
13 | 57.0.0.0/8
14 | 62.0.0.0/8
15 | 77.0.0.0/8
16 | 78.0.0.0/7
17 | 80.0.0.0/4
18 | 109.0.0.0/8
19 | 128.0.0.0/16
20 | 128.124.0.0/16
21 | 128.127.0.0/16
22 | 128.130.0.0/15
23 | 128.139.0.0/16
24 | 128.140.0.0/15
25 | 128.142.0.0/16
26 | 128.16.0.0/16
27 | 128.176.0.0/16
28 | 128.178.0.0/15
29 | 128.199.0.0/16
30 | 128.204.0.0/16
31 | 128.214.0.0/16
32 | 128.232.0.0/16
33 | 128.234.0.0/16
34 | 128.240.0.0/16
35 | 128.243.0.0/16
36 | 128.246.0.0/16
37 | 128.39.0.0/16
38 | 128.40.0.0/15
39 | 128.45.0.0/16
40 | 128.65.0.0/16
41 | 128.66.0.0/15
42 | 128.68.0.0/14
43 | 128.7.0.0/16
44 | 128.72.0.0/13
45 | 128.86.0.0/15
46 | 128.93.0.0/16
47 | 128.98.0.0/16
48 | 129.102.0.0/15
49 | 129.104.0.0/16
50 | 129.11.0.0/16
51 | 129.12.0.0/15
52 | 129.125.0.0/16
53 | 129.129.0.0/16
54 | 129.132.0.0/16
55 | 129.142.0.0/15
56 | 129.16.0.0/16
57 | 129.169.0.0/16
58 | 129.175.0.0/16
59 | 129.177.0.0/16
60 | 129.178.0.0/16
61 | 129.181.0.0/16
62 | 129.182.0.0/15
63 | 129.184.0.0/15
64 | 129.187.0.0/16
65 | 129.194.0.0/15
66 | 129.199.0.0/16
67 | 129.20.0.0/16
68 | 129.206.0.0/16
69 | 129.208.0.0/16
70 | 129.214.0.0/15
71 | 129.217.0.0/16
72 | 129.233.0.0/16
73 | 129.234.0.0/16
74 | 129.240.0.0/15
75 | 129.242.0.0/16
76 | 129.247.0.0/16
77 | 129.26.0.0/15
78 | 129.31.0.0/16
79 | 129.67.0.0/16
80 | 129.69.0.0/16
81 | 129.70.0.0/16
82 | 129.73.0.0/16
83 | 129.88.0.0/16
84 | 130.0.0.0/16
85 | 130.100.0.0/16
86 | 130.104.0.0/16
87 | 130.112.0.0/16
88 | 130.115.0.0/16
89 | 130.120.0.0/16
90 | 130.125.0.0/16
91 | 130.133.0.0/16
92 | 130.136.0.0/16
93 | 130.138.0.0/15
94 | 130.140.0.0/14
95 | 130.144.0.0/14
96 | 130.148.0.0/15
97 | 130.159.0.0/16
98 | 130.161.0.0/16
99 | 130.180.0.0/16
100 | 130.183.0.0/16
101 | 130.185.0.0/16
102 | 130.186.0.0/16
103 | 130.188.0.0/16
104 | 130.190.0.0/16
105 | 130.192.0.0/15
106 | 130.198.0.0/16
107 | 130.204.0.0/16
108 | 130.206.0.0/16
109 | 130.208.0.0/15
110 | 130.223.0.0/16
111 | 130.225.0.0/16
112 | 130.226.0.0/15
113 | 130.228.0.0/14
114 | 130.232.0.0/13
115 | 130.24.0.0/15
116 | 130.240.0.0/14
117 | 130.244.0.0/16
118 | 130.246.0.0/16
119 | 130.251.0.0/16
120 | 130.255.0.0/16
121 | 130.26.0.0/16
122 | 130.28.0.0/16
123 | 130.32.0.0/16
124 | 130.37.0.0/16
125 | 130.43.0.0/16
126 | 130.59.0.0/16
127 | 130.60.0.0/16
128 | 130.66.0.0/15
129 | 130.73.0.0/16
130 | 130.75.0.0/16
131 | 130.78.0.0/15
132 | 130.82.0.0/15
133 | 130.84.0.0/16
134 | 130.88.0.0/15
135 | 130.92.0.0/16
136 | 130.98.0.0/16
137 | 131.1.0.0/16
138 | 131.102.0.0/16
139 | 131.111.0.0/16
140 | 131.114.0.0/15
141 | 131.116.0.0/15
142 | 131.130.0.0/16
143 | 131.152.0.0/16
144 | 131.154.0.0/15
145 | 131.159.0.0/16
146 | 131.160.0.0/16
147 | 131.164.0.0/15
148 | 131.166.0.0/16
149 | 131.169.0.0/16
150 | 131.173.0.0/16
151 | 131.174.0.0/15
152 | 131.176.0.0/15
153 | 131.180.0.0/16
154 | 131.188.0.0/16
155 | 131.205.0.0/16
156 | 131.207.0.0/16
157 | 131.211.0.0/16
158 | 131.220.0.0/16
159 | 131.224.0.0/16
160 | 131.227.0.0/16
161 | 131.228.0.0/16
162 | 131.231.0.0/16
163 | 131.234.0.0/16
164 | 131.237.0.0/16
165 | 131.246.0.0/16
166 | 131.251.0.0/16
167 | 131.254.0.0/16
168 | 131.97.0.0/16
169 | 131.99.0.0/16
170 | 132.146.0.0/16
171 | 132.149.0.0/16
172 | 132.150.0.0/16
173 | 132.153.0.0/16
174 | 132.155.0.0/16
175 | 132.165.0.0/16
176 | 132.166.0.0/15
177 | 132.168.0.0/15
178 | 132.171.0.0/16
179 | 132.176.0.0/16
180 | 132.180.0.0/16
181 | 132.185.0.0/16
182 | 132.186.0.0/15
183 | 132.195.0.0/16
184 | 132.196.0.0/16
185 | 132.199.0.0/16
186 | 132.227.0.0/16
187 | 132.229.0.0/16
188 | 132.230.0.0/15
189 | 132.232.0.0/16
190 | 132.244.0.0/16
191 | 132.252.0.0/16
192 | 132.64.0.0/13
193 | 132.72.0.0/14
194 | 132.76.0.0/15
195 | 132.78.0.0/16
196 | 134.0.0.0/14
197 | 134.104.0.0/14
198 | 134.108.0.0/15
199 | 134.110.0.0/16
200 | 134.119.0.0/16
201 | 134.130.0.0/16
202 | 134.138.0.0/16
203 | 134.142.0.0/15
204 | 134.145.0.0/16
205 | 134.146.0.0/15
206 | 134.151.0.0/16
207 | 134.155.0.0/16
208 | 134.157.0.0/16
209 | 134.158.0.0/16
210 | 134.169.0.0/16
211 | 134.17.0.0/16
212 | 134.171.0.0/16
213 | 134.176.0.0/16
214 | 134.183.0.0/16
215 | 134.184.0.0/16
216 | 134.188.0.0/16
217 | 134.19.0.0/16
218 | 134.191.0.0/16
219 | 134.203.0.0/16
220 | 134.206.0.0/16
221 | 134.21.0.0/16
222 | 134.212.0.0/15
223 | 134.214.0.0/16
224 | 134.219.0.0/16
225 | 134.220.0.0/15
226 | 134.222.0.0/16
227 | 134.225.0.0/16
228 | 134.226.0.0/15
229 | 134.239.0.0/16
230 | 134.245.0.0/16
231 | 134.246.0.0/15
232 | 134.249.0.0/16
233 | 134.25.0.0/16
234 | 134.255.0.0/16
235 | 134.27.0.0/16
236 | 134.28.0.0/16
237 | 134.30.0.0/16
238 | 134.34.0.0/16
239 | 134.36.0.0/15
240 | 134.47.0.0/16
241 | 134.54.0.0/16
242 | 134.58.0.0/15
243 | 134.60.0.0/15
244 | 134.76.0.0/16
245 | 134.81.0.0/16
246 | 134.83.0.0/16
247 | 134.90.0.0/15
248 | 134.92.0.0/14
249 | 134.96.0.0/13
250 | 135.196.0.0/16
251 | 136.148.0.0/16
252 | 136.155.0.0/16
253 | 136.156.0.0/15
254 | 136.158.0.0/16
255 | 136.163.0.0/16
256 | 136.164.0.0/16
257 | 136.169.0.0/16
258 | 136.170.0.0/16
259 | 136.172.0.0/15
260 | 136.199.0.0/16
261 | 136.201.0.0/16
262 | 136.206.0.0/16
263 | 136.225.0.0/16
264 | 136.230.0.0/15
265 | 136.243.0.0/16
266 | 137.101.0.0/16
267 | 137.105.0.0/16
268 | 137.108.0.0/16
269 | 137.120.0.0/15
270 | 137.129.0.0/16
271 | 137.133.0.0/16
272 | 137.138.0.0/16
273 | 137.156.0.0/16
274 | 137.163.0.0/16
275 | 137.17.0.0/16
276 | 137.174.0.0/16
277 | 137.191.0.0/16
278 | 137.193.0.0/16
279 | 137.194.0.0/15
280 | 137.204.0.0/15
281 | 137.208.0.0/16
282 | 137.213.0.0/16
283 | 137.217.0.0/16
284 | 137.218.0.0/16
285 | 137.221.0.0/16
286 | 137.222.0.0/15
287 | 137.224.0.0/16
288 | 137.226.0.0/16
289 | 137.248.0.0/16
290 | 137.250.0.0/15
291 | 137.253.0.0/16
292 | 137.33.0.0/16
293 | 137.34.0.0/16
294 | 137.43.0.0/16
295 | 137.44.0.0/16
296 | 137.47.0.0/16
297 | 137.50.0.0/16
298 | 137.55.0.0/16
299 | 137.56.0.0/16
300 | 137.58.0.0/16
301 | 137.60.0.0/15
302 | 137.62.0.0/16
303 | 137.73.0.0/16
304 | 137.93.0.0/16
305 | 137.96.0.0/16
306 | 138.100.0.0/16
307 | 138.102.0.0/15
308 | 138.104.0.0/16
309 | 138.106.0.0/16
310 | 138.124.0.0/16
311 | 138.131.0.0/16
312 | 138.132.0.0/16
313 | 138.134.0.0/16
314 | 138.14.0.0/16
315 | 138.187.0.0/16
316 | 138.188.0.0/14
317 | 138.195.0.0/16
318 | 138.198.0.0/15
319 | 138.200.0.0/15
320 | 138.203.0.0/16
321 | 138.205.0.0/16
322 | 138.206.0.0/16
323 | 138.21.0.0/16
324 | 138.215.0.0/16
325 | 138.216.0.0/16
326 | 138.22.0.0/16
327 | 138.221.0.0/16
328 | 138.222.0.0/15
329 | 138.224.0.0/14
330 | 138.228.0.0/16
331 | 138.231.0.0/16
332 | 138.232.0.0/15
333 | 138.244.0.0/15
334 | 138.246.0.0/16
335 | 138.248.0.0/14
336 | 138.253.0.0/16
337 | 138.3.0.0/16
338 | 138.37.0.0/16
339 | 138.38.0.0/16
340 | 138.4.0.0/16
341 | 138.40.0.0/15
342 | 138.48.0.0/16
343 | 138.6.0.0/16
344 | 138.62.0.0/15
345 | 138.66.0.0/16
346 | 138.70.0.0/16
347 | 138.81.0.0/16
348 | 138.96.0.0/16
349 | 139.1.0.0/16
350 | 139.10.0.0/15
351 | 139.100.0.0/16
352 | 139.105.0.0/16
353 | 139.106.0.0/15
354 | 139.108.0.0/14
355 | 139.112.0.0/13
356 | 139.12.0.0/14
357 | 139.120.0.0/16
358 | 139.122.0.0/15
359 | 139.124.0.0/16
360 | 139.128.0.0/16
361 | 139.133.0.0/16
362 | 139.141.0.0/16
363 | 139.143.0.0/16
364 | 139.145.0.0/16
365 | 139.149.0.0/16
366 | 139.153.0.0/16
367 | 139.156.0.0/15
368 | 139.158.0.0/16
369 | 139.16.0.0/13
370 | 139.160.0.0/16
371 | 139.162.0.0/16
372 | 139.164.0.0/15
373 | 139.166.0.0/16
374 | 139.174.0.0/16
375 | 139.178.0.0/15
376 | 139.184.0.0/16
377 | 139.191.0.0/16
378 | 139.2.0.0/15
379 | 139.222.0.0/16
380 | 139.24.0.0/15
381 | 139.27.0.0/16
382 | 139.29.0.0/16
383 | 139.30.0.0/16
384 | 139.4.0.0/16
385 | 139.50.0.0/16
386 | 139.54.0.0/16
387 | 139.58.0.0/16
388 | 139.6.0.0/15
389 | 139.63.0.0/16
390 | 139.66.0.0/16
391 | 139.74.0.0/15
392 | 139.79.0.0/16
393 | 139.8.0.0/16
394 | 139.83.0.0/16
395 | 139.89.0.0/16
396 | 139.90.0.0/15
397 | 139.92.0.0/16
398 | 139.96.0.0/15
399 | 139.98.0.0/16
400 | 140.105.0.0/16
401 | 140.150.0.0/15
402 | 140.164.0.0/16
403 | 140.166.0.0/16
404 | 140.181.0.0/16
405 | 140.203.0.0/16
406 | 140.231.0.0/16
407 | 140.77.0.0/16
408 | 140.78.0.0/16
409 | 140.84.0.0/15
410 | 140.86.0.0/16
411 | 140.93.0.0/16
412 | 140.94.0.0/16
413 | 140.97.0.0/16
414 | 141.0.0.0/8
415 | 143.117.0.0/16
416 | 143.118.0.0/16
417 | 143.121.0.0/16
418 | 143.126.0.0/16
419 | 143.129.0.0/16
420 | 143.130.0.0/16
421 | 143.161.0.0/16
422 | 143.163.0.0/16
423 | 143.164.0.0/16
424 | 143.167.0.0/16
425 | 143.169.0.0/16
426 | 143.176.0.0/14
427 | 143.180.0.0/16
428 | 143.196.0.0/16
429 | 143.205.0.0/16
430 | 143.210.0.0/16
431 | 143.217.0.0/16
432 | 143.224.0.0/15
433 | 143.233.0.0/16
434 | 143.234.0.0/16
435 | 143.237.0.0/16
436 | 143.239.0.0/16
437 | 143.245.0.0/16
438 | 143.252.0.0/16
439 | 143.41.0.0/16
440 | 143.47.0.0/16
441 | 143.50.0.0/15
442 | 143.52.0.0/15
443 | 143.65.0.0/16
444 | 143.93.0.0/16
445 | 143.97.0.0/16
446 | 143.99.0.0/16
447 | 144.119.0.0/16
448 | 144.122.0.0/16
449 | 144.124.0.0/16
450 | 144.127.0.0/16
451 | 144.145.0.0/16
452 | 144.164.0.0/15
453 | 144.173.0.0/16
454 | 144.176.0.0/14
455 | 144.180.0.0/15
456 | 144.193.0.0/16
457 | 144.2.0.0/16
458 | 144.20.0.0/15
459 | 144.200.0.0/16
460 | 144.204.0.0/16
461 | 144.206.0.0/16
462 | 144.209.0.0/16
463 | 144.24.0.0/16
464 | 144.248.0.0/16
465 | 144.27.0.0/16
466 | 144.32.0.0/16
467 | 144.4.0.0/16
468 | 144.41.0.0/16
469 | 144.43.0.0/16
470 | 144.44.0.0/16
471 | 144.54.0.0/16
472 | 144.56.0.0/15
473 | 144.63.0.0/16
474 | 144.64.0.0/15
475 | 144.76.0.0/16
476 | 144.82.0.0/16
477 | 144.84.0.0/15
478 | 144.87.0.0/16
479 | 144.95.0.0/16
480 | 144.98.0.0/16
481 | 145.0.0.0/8
482 | 146.0.0.0/16
483 | 146.100.0.0/14
484 | 146.104.0.0/14
485 | 146.108.0.0/15
486 | 146.110.0.0/16
487 | 146.112.0.0/16
488 | 146.119.0.0/16
489 | 146.120.0.0/16
490 | 146.124.0.0/16
491 | 146.133.0.0/16
492 | 146.136.0.0/16
493 | 146.140.0.0/16
494 | 146.158.0.0/15
495 | 146.161.0.0/16
496 | 146.162.0.0/16
497 | 146.169.0.0/16
498 | 146.172.0.0/15
499 | 146.175.0.0/16
500 | 146.176.0.0/15
501 | 146.179.0.0/16
502 | 146.185.0.0/16
503 | 146.188.0.0/16
504 | 146.19.0.0/16
505 | 146.191.0.0/16
506 | 146.192.0.0/15
507 | 146.194.0.0/16
508 | 146.2.0.0/15
509 | 146.21.0.0/16
510 | 146.210.0.0/15
511 | 146.212.0.0/15
512 | 146.216.0.0/16
513 | 146.219.0.0/16
514 | 146.220.0.0/16
515 | 146.224.0.0/16
516 | 146.227.0.0/16
517 | 146.228.0.0/16
518 | 146.234.0.0/16
519 | 146.247.0.0/16
520 | 146.248.0.0/15
521 | 146.251.0.0/16
522 | 146.253.0.0/16
523 | 146.254.0.0/15
524 | 146.4.0.0/16
525 | 146.48.0.0/16
526 | 146.50.0.0/16
527 | 146.52.0.0/16
528 | 146.59.0.0/16
529 | 146.60.0.0/16
530 | 146.66.0.0/15
531 | 146.70.0.0/16
532 | 146.72.0.0/16
533 | 146.75.0.0/16
534 | 146.77.0.0/16
535 | 146.80.0.0/15
536 | 146.87.0.0/16
537 | 146.90.0.0/16
538 | 146.97.0.0/16
539 | 147.100.0.0/16
540 | 147.102.0.0/16
541 | 147.111.0.0/16
542 | 147.112.0.0/16
543 | 147.119.0.0/16
544 | 147.12.0.0/15
545 | 147.122.0.0/15
546 | 147.125.0.0/16
547 | 147.127.0.0/16
548 | 147.14.0.0/16
549 | 147.142.0.0/15
550 | 147.147.0.0/16
551 | 147.148.0.0/14
552 | 147.152.0.0/16
553 | 147.156.0.0/16
554 | 147.161.0.0/16
555 | 147.162.0.0/15
556 | 147.167.0.0/16
557 | 147.171.0.0/16
558 | 147.172.0.0/15
559 | 147.175.0.0/16
560 | 147.180.0.0/15
561 | 147.184.0.0/16
562 | 147.186.0.0/16
563 | 147.188.0.0/15
564 | 147.193.0.0/16
565 | 147.196.0.0/15
566 | 147.201.0.0/16
567 | 147.204.0.0/16
568 | 147.210.0.0/16
569 | 147.213.0.0/16
570 | 147.214.0.0/15
571 | 147.220.0.0/16
572 | 147.228.0.0/14
573 | 147.232.0.0/14
574 | 147.236.0.0/15
575 | 147.243.0.0/16
576 | 147.250.0.0/15
577 | 147.252.0.0/16
578 | 147.27.0.0/16
579 | 147.29.0.0/16
580 | 147.30.0.0/16
581 | 147.32.0.0/15
582 | 147.44.0.0/15
583 | 147.52.0.0/16
584 | 147.54.0.0/16
585 | 147.60.0.0/16
586 | 147.67.0.0/16
587 | 147.68.0.0/16
588 | 147.7.0.0/16
589 | 147.75.0.0/16
590 | 147.77.0.0/16
591 | 147.83.0.0/16
592 | 147.84.0.0/16
593 | 147.86.0.0/15
594 | 147.88.0.0/15
595 | 147.91.0.0/16
596 | 147.93.0.0/16
597 | 147.94.0.0/15
598 | 147.96.0.0/16
599 | 147.98.0.0/15
600 | 148.110.0.0/16
601 | 148.118.0.0/15
602 | 148.120.0.0/14
603 | 148.135.0.0/16
604 | 148.136.0.0/16
605 | 148.138.0.0/16
606 | 148.140.0.0/16
607 | 148.143.0.0/16
608 | 148.148.0.0/16
609 | 148.151.0.0/16
610 | 148.160.0.0/16
611 | 148.169.0.0/16
612 | 148.176.0.0/16
613 | 148.181.0.0/16
614 | 148.185.0.0/16
615 | 148.187.0.0/16
616 | 148.196.0.0/15
617 | 148.198.0.0/16
618 | 148.2.0.0/15
619 | 148.200.0.0/16
620 | 148.251.0.0/16
621 | 148.252.0.0/15
622 | 148.54.0.0/16
623 | 148.56.0.0/16
624 | 148.6.0.0/16
625 | 148.60.0.0/16
626 | 148.79.0.0/16
627 | 148.81.0.0/16
628 | 148.82.0.0/15
629 | 148.88.0.0/16
630 | 149.0.0.0/16
631 | 149.126.0.0/16
632 | 149.132.0.0/15
633 | 149.134.0.0/16
634 | 149.139.0.0/16
635 | 149.140.0.0/16
636 | 149.146.0.0/15
637 | 149.148.0.0/16
638 | 149.153.0.0/16
639 | 149.154.0.0/15
640 | 149.156.0.0/15
641 | 149.170.0.0/16
642 | 149.172.0.0/16
643 | 149.177.0.0/16
644 | 149.178.0.0/15
645 | 149.180.0.0/14
646 | 149.184.0.0/13
647 | 149.192.0.0/14
648 | 149.196.0.0/15
649 | 149.200.0.0/13
650 | 149.208.0.0/12
651 | 149.224.0.0/12
652 | 149.240.0.0/13
653 | 149.249.0.0/16
654 | 149.250.0.0/15
655 | 149.254.0.0/15
656 | 149.27.0.0/16
657 | 149.3.0.0/16
658 | 149.49.0.0/16
659 | 149.59.0.0/16
660 | 149.62.0.0/16
661 | 150.106.0.0/16
662 | 150.128.0.0/16
663 | 150.132.0.0/16
664 | 150.140.0.0/16
665 | 150.145.0.0/16
666 | 150.146.0.0/16
667 | 150.158.0.0/16
668 | 150.175.0.0/16
669 | 150.178.0.0/16
670 | 150.204.0.0/15
671 | 150.213.0.0/16
672 | 150.214.0.0/16
673 | 150.217.0.0/16
674 | 150.227.0.0/16
675 | 150.236.0.0/15
676 | 150.241.0.0/16
677 | 150.244.0.0/16
678 | 150.251.0.0/16
679 | 150.254.0.0/16
680 | 151.0.0.0/8
681 | 152.105.0.0/16
682 | 152.114.0.0/15
683 | 152.134.0.0/16
684 | 152.143.0.0/16
685 | 152.150.0.0/16
686 | 152.152.0.0/16
687 | 152.66.0.0/16
688 | 152.71.0.0/16
689 | 152.73.0.0/16
690 | 152.77.0.0/16
691 | 152.78.0.0/16
692 | 152.81.0.0/16
693 | 152.88.0.0/16
694 | 152.90.0.0/16
695 | 152.93.0.0/16
696 | 152.94.0.0/15
697 | 152.96.0.0/16
698 | 153.1.0.0/16
699 | 153.100.0.0/16
700 | 153.108.0.0/15
701 | 153.110.0.0/16
702 | 153.112.0.0/16
703 | 153.15.0.0/16
704 | 153.17.0.0/16
705 | 153.19.0.0/16
706 | 153.5.0.0/16
707 | 153.88.0.0/16
708 | 153.92.0.0/14
709 | 153.96.0.0/15
710 | 153.98.0.0/16
711 | 154.14.0.0/15
712 | 154.32.0.0/16
713 | 154.8.0.0/16
714 | 155.105.0.0/16
715 | 155.131.0.0/16
716 | 155.132.0.0/15
717 | 155.136.0.0/15
718 | 155.140.0.0/16
719 | 155.145.0.0/16
720 | 155.158.0.0/16
721 | 155.185.0.0/16
722 | 155.192.0.0/16
723 | 155.198.0.0/16
724 | 155.202.0.0/16
725 | 155.204.0.0/16
726 | 155.207.0.0/16
727 | 155.209.0.0/16
728 | 155.210.0.0/16
729 | 155.223.0.0/16
730 | 155.227.0.0/16
731 | 155.228.0.0/16
732 | 155.231.0.0/16
733 | 155.245.0.0/16
734 | 155.249.0.0/16
735 | 155.250.0.0/16
736 | 155.253.0.0/16
737 | 155.4.0.0/16
738 | 155.45.0.0/16
739 | 155.54.0.0/15
740 | 155.56.0.0/16
741 | 155.66.0.0/16
742 | 155.73.0.0/16
743 | 156.10.0.0/16
744 | 156.106.0.0/16
745 | 156.114.0.0/15
746 | 156.116.0.0/16
747 | 156.118.0.0/16
748 | 156.133.0.0/16
749 | 156.135.0.0/16
750 | 156.14.0.0/16
751 | 156.148.0.0/16
752 | 156.150.0.0/16
753 | 156.17.0.0/16
754 | 156.18.0.0/16
755 | 156.25.0.0/16
756 | 156.28.0.0/16
757 | 156.35.0.0/16
758 | 156.43.0.0/16
759 | 156.48.0.0/15
760 | 156.51.0.0/16
761 | 156.52.0.0/16
762 | 156.54.0.0/16
763 | 156.58.0.0/16
764 | 156.61.0.0/16
765 | 156.67.0.0/16
766 | 156.83.0.0/16
767 | 157.124.0.0/15
768 | 157.129.0.0/16
769 | 157.136.0.0/16
770 | 157.138.0.0/16
771 | 157.140.0.0/16
772 | 157.144.0.0/16
773 | 157.157.0.0/16
774 | 157.158.0.0/15
775 | 157.161.0.0/16
776 | 157.162.0.0/15
777 | 157.164.0.0/16
778 | 157.167.0.0/16
779 | 157.168.0.0/15
780 | 157.171.0.0/16
781 | 157.172.0.0/15
782 | 157.177.0.0/16
783 | 157.180.0.0/15
784 | 157.186.0.0/16
785 | 157.190.0.0/16
786 | 157.193.0.0/16
787 | 157.200.0.0/16
788 | 157.203.0.0/16
789 | 157.228.0.0/16
790 | 157.23.0.0/16
791 | 157.236.0.0/15
792 | 157.24.0.0/14
793 | 157.243.0.0/16
794 | 157.247.0.0/16
795 | 157.249.0.0/16
796 | 157.28.0.0/15
797 | 157.83.0.0/16
798 | 157.84.0.0/16
799 | 157.88.0.0/16
800 | 157.94.0.0/16
801 | 157.96.0.0/16
802 | 157.99.0.0/16
803 | 158.102.0.0/16
804 | 158.105.0.0/16
805 | 158.109.0.0/16
806 | 158.110.0.0/16
807 | 158.112.0.0/16
808 | 158.119.0.0/16
809 | 158.124.0.0/14
810 | 158.129.0.0/16
811 | 158.131.0.0/16
812 | 158.133.0.0/16
813 | 158.143.0.0/16
814 | 158.148.0.0/15
815 | 158.150.0.0/16
816 | 158.152.0.0/16
817 | 158.156.0.0/16
818 | 158.162.0.0/16
819 | 158.166.0.0/15
820 | 158.168.0.0/15
821 | 158.172.0.0/14
822 | 158.176.0.0/14
823 | 158.180.0.0/15
824 | 158.190.0.0/15
825 | 158.192.0.0/14
826 | 158.196.0.0/15
827 | 158.216.0.0/16
828 | 158.218.0.0/16
829 | 158.220.0.0/16
830 | 158.223.0.0/16
831 | 158.225.0.0/16
832 | 158.226.0.0/15
833 | 158.230.0.0/15
834 | 158.232.0.0/15
835 | 158.234.0.0/16
836 | 158.248.0.0/15
837 | 158.250.0.0/16
838 | 158.255.0.0/16
839 | 158.36.0.0/14
840 | 158.41.0.0/16
841 | 158.42.0.0/15
842 | 158.46.0.0/15
843 | 158.49.0.0/16
844 | 158.50.0.0/16
845 | 158.58.0.0/16
846 | 158.64.0.0/16
847 | 158.66.0.0/15
848 | 158.75.0.0/16
849 | 158.90.0.0/16
850 | 158.92.0.0/16
851 | 158.94.0.0/16
852 | 158.99.0.0/16
853 | 159.0.0.0/16
854 | 159.100.0.0/15
855 | 159.103.0.0/16
856 | 159.104.0.0/16
857 | 159.107.0.0/16
858 | 159.109.0.0/16
859 | 159.114.0.0/16
860 | 159.12.0.0/16
861 | 159.122.0.0/16
862 | 159.130.0.0/16
863 | 159.134.0.0/16
864 | 159.144.0.0/16
865 | 159.146.0.0/15
866 | 159.148.0.0/15
867 | 159.15.0.0/16
868 | 159.151.0.0/16
869 | 159.152.0.0/16
870 | 159.154.0.0/16
871 | 159.156.0.0/16
872 | 159.160.0.0/16
873 | 159.162.0.0/16
874 | 159.167.0.0/16
875 | 159.168.0.0/16
876 | 159.170.0.0/15
877 | 159.173.0.0/16
878 | 159.179.0.0/16
879 | 159.180.0.0/16
880 | 159.190.0.0/16
881 | 159.193.0.0/16
882 | 159.194.0.0/15
883 | 159.197.0.0/16
884 | 159.20.0.0/16
885 | 159.200.0.0/16
886 | 159.205.0.0/16
887 | 159.210.0.0/16
888 | 159.213.0.0/16
889 | 159.216.0.0/15
890 | 159.219.0.0/16
891 | 159.22.0.0/15
892 | 159.224.0.0/16
893 | 159.232.0.0/16
894 | 159.236.0.0/15
895 | 159.239.0.0/16
896 | 159.241.0.0/16
897 | 159.244.0.0/15
898 | 159.25.0.0/16
899 | 159.253.0.0/16
900 | 159.254.0.0/15
901 | 159.29.0.0/16
902 | 159.30.0.0/15
903 | 159.34.0.0/16
904 | 159.38.0.0/16
905 | 159.46.0.0/16
906 | 159.50.0.0/15
907 | 159.58.0.0/16
908 | 159.60.0.0/16
909 | 159.7.0.0/16
910 | 159.72.0.0/16
911 | 159.8.0.0/16
912 | 159.81.0.0/16
913 | 159.84.0.0/16
914 | 159.86.0.0/16
915 | 159.92.0.0/15
916 | 159.95.0.0/16
917 | 160.100.0.0/16
918 | 160.103.0.0/16
919 | 160.104.0.0/16
920 | 160.114.0.0/16
921 | 160.180.0.0/16
922 | 160.210.0.0/15
923 | 160.213.0.0/16
924 | 160.214.0.0/16
925 | 160.216.0.0/14
926 | 160.220.0.0/15
927 | 160.228.0.0/16
928 | 160.38.0.0/16
929 | 160.40.0.0/16
930 | 160.44.0.0/14
931 | 160.48.0.0/12
932 | 160.5.0.0/16
933 | 160.6.0.0/16
934 | 160.66.0.0/15
935 | 160.68.0.0/16
936 | 160.70.0.0/15
937 | 160.75.0.0/16
938 | 160.78.0.0/16
939 | 160.8.0.0/15
940 | 160.80.0.0/16
941 | 160.85.0.0/16
942 | 160.92.0.0/16
943 | 160.97.0.0/16
944 | 160.98.0.0/15
945 | 161.104.0.0/15
946 | 161.106.0.0/16
947 | 161.110.0.0/15
948 | 161.112.0.0/16
949 | 161.116.0.0/16
950 | 161.12.0.0/16
951 | 161.134.0.0/16
952 | 161.147.0.0/16
953 | 161.158.0.0/16
954 | 161.17.0.0/16
955 | 161.2.0.0/15
956 | 161.20.0.0/16
957 | 161.202.0.0/16
958 | 161.218.0.0/16
959 | 161.23.0.0/16
960 | 161.252.0.0/16
961 | 161.27.0.0/16
962 | 161.30.0.0/16
963 | 161.37.0.0/16
964 | 161.4.0.0/15
965 | 161.41.0.0/16
966 | 161.42.0.0/16
967 | 161.48.0.0/16
968 | 161.52.0.0/15
969 | 161.54.0.0/16
970 | 161.59.0.0/16
971 | 161.62.0.0/16
972 | 161.67.0.0/16
973 | 161.71.0.0/16
974 | 161.72.0.0/15
975 | 161.74.0.0/16
976 | 161.76.0.0/16
977 | 161.78.0.0/16
978 | 161.8.0.0/15
979 | 161.83.0.0/16
980 | 161.84.0.0/14
981 | 161.88.0.0/14
982 | 161.92.0.0/16
983 | 162.11.0.0/16
984 | 162.13.0.0/16
985 | 162.21.0.0/16
986 | 162.23.0.0/16
987 | 162.25.0.0/16
988 | 162.26.0.0/16
989 | 162.38.0.0/16
990 | 162.86.0.0/16
991 | 163.1.0.0/16
992 | 163.112.0.0/14
993 | 163.116.0.0/15
994 | 163.119.0.0/16
995 | 163.156.0.0/14
996 | 163.160.0.0/12
997 | 163.242.0.0/16
998 | 163.3.0.0/16
999 | 163.34.0.0/16
1000 | 163.5.0.0/16
1001 | 163.62.0.0/15
1002 | 163.64.0.0/11
1003 | 163.9.0.0/16
1004 | 163.96.0.0/12
1005 | 164.0.0.0/11
1006 | 164.126.0.0/15
1007 | 164.128.0.0/12
1008 | 164.177.0.0/16
1009 | 164.215.0.0/16
1010 | 164.32.0.0/13
1011 | 164.40.0.0/16
1012 | 164.48.0.0/16
1013 | 164.59.0.0/16
1014 | 164.60.0.0/15
1015 | 164.81.0.0/16
1016 | 165.114.0.0/16
1017 | 165.218.0.0/16
1018 | 165.222.0.0/16
1019 | 166.49.128.0/17
1020 | 166.8.0.0/13
1021 | 166.87.0.0/16
1022 | 167.111.0.0/16
1023 | 167.168.0.0/16
1024 | 167.172.0.0/16
1025 | 167.203.0.0/16
1026 | 167.81.0.0/16
1027 | 168.1.0.0/16
1028 | 168.139.0.0/16
1029 | 168.187.0.0/16
1030 | 169.32.0.0/11
1031 | 170.236.0.0/15
1032 | 170.255.0.0/16
1033 | 170.60.0.0/16
1034 | 171.16.0.0/12
1035 | 171.32.0.0/15
1036 | 176.0.0.0/8
1037 | 178.0.0.0/8
1038 | 185.0.0.0/8
1039 | 188.0.0.0/8
1040 | 192.100.102.0/23
1041 | 192.100.104.0/21
1042 | 192.100.112.0/20
1043 | 192.100.128.0/22
1044 | 192.100.132.0/23
1045 | 192.100.135.0/24
1046 | 192.100.136.0/22
1047 | 192.100.140.0/24
1048 | 192.100.144.0/24
1049 | 192.100.154.0/24
1050 | 192.100.18.0/24
1051 | 192.100.23.0/24
1052 | 192.100.24.0/23
1053 | 192.100.52.0/24
1054 | 192.100.61.0/24
1055 | 192.100.63.0/24
1056 | 192.100.78.0/24
1057 | 192.100.96.0/22
1058 | 192.101.1.0/24
1059 | 192.101.11.0/24
1060 | 192.101.118.0/24
1061 | 192.101.137.0/24
1062 | 192.101.161.0/24
1063 | 192.101.162.0/23
1064 | 192.101.164.0/22
1065 | 192.101.168.0/24
1066 | 192.101.170.0/24
1067 | 192.101.176.0/24
1068 | 192.101.179.0/24
1069 | 192.101.180.0/24
1070 | 192.101.192.0/24
1071 | 192.101.197.0/24
1072 | 192.101.198.0/24
1073 | 192.101.252.0/24
1074 | 192.101.28.0/24
1075 | 192.101.34.0/24
1076 | 192.101.4.0/24
1077 | 192.101.75.0/24
1078 | 192.101.8.0/24
1079 | 192.101.81.0/24
1080 | 192.101.82.0/23
1081 | 192.101.84.0/22
1082 | 192.101.88.0/23
1083 | 192.101.90.0/24
1084 | 192.102.1.0/24
1085 | 192.102.146.0/23
1086 | 192.102.148.0/22
1087 | 192.102.152.0/21
1088 | 192.102.160.0/20
1089 | 192.102.17.0/24
1090 | 192.102.176.0/23
1091 | 192.102.18.0/23
1092 | 192.102.20.0/22
1093 | 192.102.214.0/24
1094 | 192.102.224.0/23
1095 | 192.102.227.0/24
1096 | 192.102.228.0/23
1097 | 192.102.24.0/21
1098 | 192.102.32.0/19
1099 | 192.102.6.0/23
1100 | 192.102.64.0/20
1101 | 192.102.8.0/24
1102 | 192.102.80.0/23
1103 | 192.102.89.0/24
1104 | 192.102.95.0/24
1105 | 192.103.112.0/22
1106 | 192.103.116.0/24
1107 | 192.103.137.0/24
1108 | 192.103.138.0/23
1109 | 192.103.14.0/24
1110 | 192.103.147.0/24
1111 | 192.103.2.0/24
1112 | 192.103.20.0/24
1113 | 192.103.23.0/24
1114 | 192.103.27.0/24
1115 | 192.103.28.0/22
1116 | 192.103.32.0/21
1117 | 192.103.40.0/24
1118 | 192.103.7.0/24
1119 | 192.103.85.0/24
1120 | 192.103.86.0/23
1121 | 192.103.88.0/21
1122 | 192.103.96.0/20
1123 | 192.104.140.0/24
1124 | 192.104.142.0/24
1125 | 192.104.147.0/24
1126 | 192.104.154.0/23
1127 | 192.104.167.0/24
1128 | 192.104.168.0/24
1129 | 192.104.23.0/24
1130 | 192.104.238.0/24
1131 | 192.104.245.0/24
1132 | 192.104.248.0/24
1133 | 192.104.251.0/24
1134 | 192.104.28.0/23
1135 | 192.104.35.0/24
1136 | 192.104.36.0/23
1137 | 192.104.41.0/24
1138 | 192.104.48.0/24
1139 | 192.104.53.0/24
1140 | 192.104.55.0/24
1141 | 192.104.56.0/23
1142 | 192.104.58.0/24
1143 | 192.104.72.0/24
1144 | 192.104.77.0/24
1145 | 192.104.82.0/24
1146 | 192.105.75.0/24
1147 | 192.106.0.0/16
1148 | 192.107.100.0/24
1149 | 192.107.11.0/24
1150 | 192.107.110.0/24
1151 | 192.107.114.0/24
1152 | 192.107.12.0/23
1153 | 192.107.122.0/23
1154 | 192.107.124.0/22
1155 | 192.107.128.0/23
1156 | 192.107.132.0/24
1157 | 192.107.168.0/24
1158 | 192.107.174.0/24
1159 | 192.107.177.0/24
1160 | 192.107.178.0/24
1161 | 192.107.187.0/24
1162 | 192.107.2.0/24
1163 | 192.107.200.0/21
1164 | 192.107.208.0/20
1165 | 192.107.224.0/21
1166 | 192.107.232.0/23
1167 | 192.107.235.0/24
1168 | 192.107.236.0/24
1169 | 192.107.4.0/23
1170 | 192.107.51.0/24
1171 | 192.107.52.0/22
1172 | 192.107.56.0/21
1173 | 192.107.64.0/19
1174 | 192.107.96.0/22
1175 | 192.108.100.0/23
1176 | 192.108.107.0/24
1177 | 192.108.108.0/24
1178 | 192.108.114.0/23
1179 | 192.108.116.0/22
1180 | 192.108.120.0/23
1181 | 192.108.125.0/24
1182 | 192.108.126.0/24
1183 | 192.108.128.0/19
1184 | 192.108.160.0/21
1185 | 192.108.168.0/22
1186 | 192.108.172.0/23
1187 | 192.108.174.0/24
1188 | 192.108.195.0/24
1189 | 192.108.196.0/22
1190 | 192.108.200.0/21
1191 | 192.108.208.0/22
1192 | 192.108.212.0/23
1193 | 192.108.214.0/24
1194 | 192.108.23.0/24
1195 | 192.108.234.0/24
1196 | 192.108.238.0/24
1197 | 192.108.24.0/21
1198 | 192.108.32.0/20
1199 | 192.108.48.0/23
1200 | 192.108.51.0/24
1201 | 192.108.52.0/22
1202 | 192.108.56.0/21
1203 | 192.108.64.0/20
1204 | 192.108.80.0/21
1205 | 192.108.88.0/22
1206 | 192.108.92.0/24
1207 | 192.109.0.0/19
1208 | 192.109.100.0/23
1209 | 192.109.102.0/24
1210 | 192.109.105.0/24
1211 | 192.109.106.0/23
1212 | 192.109.108.0/22
1213 | 192.109.112.0/21
1214 | 192.109.121.0/24
1215 | 192.109.122.0/23
1216 | 192.109.124.0/22
1217 | 192.109.128.0/18
1218 | 192.109.192.0/19
1219 | 192.109.224.0/20
1220 | 192.109.240.0/23
1221 | 192.109.243.0/24
1222 | 192.109.244.0/22
1223 | 192.109.248.0/21
1224 | 192.109.32.0/21
1225 | 192.109.40.0/22
1226 | 192.109.44.0/24
1227 | 192.109.46.0/23
1228 | 192.109.48.0/20
1229 | 192.109.64.0/21
1230 | 192.109.72.0/23
1231 | 192.109.74.0/24
1232 | 192.109.76.0/22
1233 | 192.109.80.0/21
1234 | 192.109.88.0/22
1235 | 192.109.94.0/23
1236 | 192.109.96.0/23
1237 | 192.109.98.0/24
1238 | 192.111.101.0/24
1239 | 192.111.103.0/24
1240 | 192.111.104.0/24
1241 | 192.111.124.0/23
1242 | 192.111.127.0/24
1243 | 192.111.252.0/24
1244 | 192.111.33.0/24
1245 | 192.111.39.0/24
1246 | 192.111.44.0/24
1247 | 192.111.47.0/24
1248 | 192.111.48.0/24
1249 | 192.111.88.0/24
1250 | 192.112.100.0/24
1251 | 192.112.204.0/24
1252 | 192.112.206.0/24
1253 | 192.112.208.0/24
1254 | 192.112.213.0/24
1255 | 192.112.214.0/24
1256 | 192.112.247.0/24
1257 | 192.112.254.0/24
1258 | 192.112.30.0/23
1259 | 192.112.32.0/24
1260 | 192.112.45.0/24
1261 | 192.112.49.0/24
1262 | 192.112.61.0/24
1263 | 192.112.70.0/23
1264 | 192.112.72.0/21
1265 | 192.112.98.0/23
1266 | 192.113.0.0/16
1267 | 192.114.0.0/15
1268 | 192.116.0.0/15
1269 | 192.118.0.0/16
1270 | 192.12.1.0/24
1271 | 192.12.192.0/23
1272 | 192.12.194.0/24
1273 | 192.12.217.0/24
1274 | 192.12.218.0/24
1275 | 192.12.231.0/24
1276 | 192.12.232.0/24
1277 | 192.12.235.0/24
1278 | 192.12.247.0/24
1279 | 192.12.47.0/24
1280 | 192.12.54.0/24
1281 | 192.12.72.0/23
1282 | 192.12.77.0/24
1283 | 192.12.81.0/24
1284 | 192.12.96.0/24
1285 | 192.12.99.0/24
1286 | 192.121.0.0/16
1287 | 192.122.1.0/24
1288 | 192.122.128.0/23
1289 | 192.122.130.0/24
1290 | 192.122.141.0/24
1291 | 192.122.142.0/23
1292 | 192.122.144.0/23
1293 | 192.122.146.0/24
1294 | 192.122.151.0/24
1295 | 192.122.152.0/21
1296 | 192.122.16.0/20
1297 | 192.122.160.0/21
1298 | 192.122.168.0/23
1299 | 192.122.170.0/24
1300 | 192.122.2.0/23
1301 | 192.122.214.0/24
1302 | 192.122.216.0/21
1303 | 192.122.224.0/21
1304 | 192.122.232.0/23
1305 | 192.122.234.0/24
1306 | 192.122.238.0/23
1307 | 192.122.240.0/23
1308 | 192.122.242.0/24
1309 | 192.122.254.0/24
1310 | 192.122.32.0/19
1311 | 192.122.4.0/22
1312 | 192.122.64.0/18
1313 | 192.122.8.0/21
1314 | 192.124.112.0/24
1315 | 192.124.115.0/24
1316 | 192.124.116.0/24
1317 | 192.124.155.0/24
1318 | 192.124.170.0/23
1319 | 192.124.172.0/22
1320 | 192.124.176.0/20
1321 | 192.124.192.0/20
1322 | 192.124.208.0/21
1323 | 192.124.216.0/22
1324 | 192.124.235.0/24
1325 | 192.124.237.0/24
1326 | 192.124.238.0/23
1327 | 192.124.240.0/22
1328 | 192.124.244.0/23
1329 | 192.124.247.0/24
1330 | 192.124.248.0/24
1331 | 192.124.25.0/24
1332 | 192.124.250.0/23
1333 | 192.124.252.0/23
1334 | 192.124.254.0/24
1335 | 192.124.26.0/23
1336 | 192.124.28.0/24
1337 | 192.124.32.0/24
1338 | 192.124.39.0/24
1339 | 192.124.46.0/24
1340 | 192.125.0.0/16
1341 | 192.126.1.0/24
1342 | 192.126.16.0/20
1343 | 192.126.2.0/23
1344 | 192.126.32.0/19
1345 | 192.126.4.0/22
1346 | 192.126.64.0/24
1347 | 192.126.8.0/21
1348 | 192.129.1.0/24
1349 | 192.129.16.0/20
1350 | 192.129.2.0/23
1351 | 192.129.32.0/20
1352 | 192.129.4.0/22
1353 | 192.129.48.0/21
1354 | 192.129.56.0/22
1355 | 192.129.60.0/23
1356 | 192.129.8.0/21
1357 | 192.129.80.0/24
1358 | 192.129.87.0/24
1359 | 192.129.98.0/24
1360 | 192.130.0.0/16
1361 | 192.131.108.0/24
1362 | 192.131.132.0/24
1363 | 192.131.20.0/24
1364 | 192.131.25.0/24
1365 | 192.131.26.0/24
1366 | 192.131.79.0/24
1367 | 192.131.89.0/24
1368 | 192.131.96.0/24
1369 | 192.132.10.0/23
1370 | 192.132.239.0/24
1371 | 192.132.244.0/23
1372 | 192.132.252.0/24
1373 | 192.132.34.0/24
1374 | 192.132.53.0/24
1375 | 192.132.55.0/24
1376 | 192.132.9.0/24
1377 | 192.132.99.0/24
1378 | 192.133.108.0/22
1379 | 192.133.121.0/24
1380 | 192.133.131.0/24
1381 | 192.133.15.0/24
1382 | 192.133.244.0/24
1383 | 192.133.28.0/24
1384 | 192.133.32.0/24
1385 | 192.133.36.0/24
1386 | 192.133.53.0/24
1387 | 192.133.54.0/23
1388 | 192.133.58.0/24
1389 | 192.133.64.0/24
1390 | 192.134.0.0/16
1391 | 192.135.129.0/24
1392 | 192.135.133.0/24
1393 | 192.135.143.0/24
1394 | 192.135.145.0/24
1395 | 192.135.146.0/23
1396 | 192.135.148.0/22
1397 | 192.135.152.0/21
1398 | 192.135.16.0/20
1399 | 192.135.160.0/21
1400 | 192.135.168.0/24
1401 | 192.135.175.0/24
1402 | 192.135.187.0/24
1403 | 192.135.219.0/24
1404 | 192.135.225.0/24
1405 | 192.135.231.0/24
1406 | 192.135.232.0/23
1407 | 192.135.234.0/24
1408 | 192.135.253.0/24
1409 | 192.135.254.0/24
1410 | 192.135.32.0/22
1411 | 192.135.36.0/23
1412 | 192.135.46.0/24
1413 | 192.135.51.0/24
1414 | 192.135.52.0/23
1415 | 192.135.63.0/24
1416 | 192.135.66.0/24
1417 | 192.135.68.0/24
1418 | 192.135.7.0/24
1419 | 192.135.8.0/21
1420 | 192.135.82.0/24
1421 | 192.136.100.0/23
1422 | 192.136.102.0/24
1423 | 192.136.154.0/23
1424 | 192.136.156.0/24
1425 | 192.136.18.0/23
1426 | 192.136.23.0/24
1427 | 192.136.29.0/24
1428 | 192.136.30.0/23
1429 | 192.136.40.0/23
1430 | 192.136.49.0/24
1431 | 192.136.51.0/24
1432 | 192.136.52.0/24
1433 | 192.136.61.0/24
1434 | 192.136.7.0/24
1435 | 192.136.71.0/24
1436 | 192.136.72.0/21
1437 | 192.136.80.0/20
1438 | 192.136.9.0/24
1439 | 192.136.96.0/22
1440 | 192.138.1.0/24
1441 | 192.138.105.0/24
1442 | 192.138.106.0/23
1443 | 192.138.108.0/22
1444 | 192.138.112.0/22
1445 | 192.138.116.0/23
1446 | 192.138.155.0/24
1447 | 192.138.156.0/23
1448 | 192.138.158.0/24
1449 | 192.138.183.0/24
1450 | 192.138.192.0/24
1451 | 192.138.2.0/23
1452 | 192.138.204.0/24
1453 | 192.138.228.0/22
1454 | 192.138.232.0/24
1455 | 192.138.248.0/24
1456 | 192.138.4.0/22
1457 | 192.138.8.0/24
1458 | 192.138.86.0/24
1459 | 192.139.78.0/24
1460 | 192.144.74.0/24
1461 | 192.144.76.0/23
1462 | 192.146.117.0/24
1463 | 192.146.119.0/24
1464 | 192.146.123.0/24
1465 | 192.146.124.0/23
1466 | 192.146.126.0/24
1467 | 192.146.132.0/24
1468 | 192.146.134.0/23
1469 | 192.146.136.0/22
1470 | 192.146.140.0/23
1471 | 192.146.152.0/24
1472 | 192.146.163.0/24
1473 | 192.146.164.0/22
1474 | 192.146.168.0/23
1475 | 192.146.170.0/24
1476 | 192.146.172.0/22
1477 | 192.146.176.0/22
1478 | 192.146.180.0/23
1479 | 192.146.182.0/24
1480 | 192.146.185.0/24
1481 | 192.146.187.0/24
1482 | 192.146.193.0/24
1483 | 192.146.204.0/24
1484 | 192.146.227.0/24
1485 | 192.146.228.0/24
1486 | 192.146.233.0/24
1487 | 192.146.234.0/24
1488 | 192.146.238.0/23
1489 | 192.146.242.0/24
1490 | 192.147.141.0/24
1491 | 192.147.150.0/24
1492 | 192.147.155.0/24
1493 | 192.147.212.0/24
1494 | 192.147.215.0/24
1495 | 192.147.216.0/23
1496 | 192.147.219.0/24
1497 | 192.147.228.0/24
1498 | 192.147.23.0/24
1499 | 192.147.247.0/24
1500 | 192.147.251.0/24
1501 | 192.147.34.0/24
1502 | 192.147.36.0/24
1503 | 192.147.42.0/24
1504 | 192.147.76.0/22
1505 | 192.148.103.0/24
1506 | 192.148.166.0/23
1507 | 192.148.177.0/24
1508 | 192.148.178.0/23
1509 | 192.148.180.0/22
1510 | 192.148.184.0/23
1511 | 192.148.186.0/24
1512 | 192.148.192.0/23
1513 | 192.148.194.0/24
1514 | 192.148.198.0/23
1515 | 192.148.200.0/21
1516 | 192.148.208.0/21
1517 | 192.148.216.0/24
1518 | 192.148.220.0/24
1519 | 192.148.33.0/24
1520 | 192.148.34.0/23
1521 | 192.148.36.0/22
1522 | 192.148.40.0/21
1523 | 192.148.48.0/20
1524 | 192.148.64.0/20
1525 | 192.148.80.0/21
1526 | 192.148.88.0/22
1527 | 192.148.92.0/24
1528 | 192.149.100.0/24
1529 | 192.149.102.0/24
1530 | 192.149.110.0/23
1531 | 192.149.117.0/24
1532 | 192.149.118.0/23
1533 | 192.149.120.0/23
1534 | 192.149.126.0/24
1535 | 192.149.15.0/24
1536 | 192.149.19.0/24
1537 | 192.149.227.0/24
1538 | 192.149.232.0/24
1539 | 192.149.238.0/24
1540 | 192.149.27.0/24
1541 | 192.149.29.0/24
1542 | 192.149.3.0/24
1543 | 192.149.30.0/23
1544 | 192.149.32.0/23
1545 | 192.149.35.0/24
1546 | 192.149.41.0/24
1547 | 192.149.5.0/24
1548 | 192.149.57.0/24
1549 | 192.149.59.0/24
1550 | 192.149.60.0/24
1551 | 192.149.77.0/24
1552 | 192.149.78.0/23
1553 | 192.150.104.0/24
1554 | 192.150.106.0/24
1555 | 192.150.124.0/24
1556 | 192.150.140.0/24
1557 | 192.150.146.0/24
1558 | 192.150.177.0/24
1559 | 192.150.178.0/23
1560 | 192.150.180.0/22
1561 | 192.150.184.0/24
1562 | 192.150.188.0/23
1563 | 192.150.190.0/24
1564 | 192.150.192.0/22
1565 | 192.150.196.0/23
1566 | 192.150.198.0/24
1567 | 192.150.203.0/24
1568 | 192.150.204.0/23
1569 | 192.150.208.0/23
1570 | 192.150.223.0/24
1571 | 192.150.227.0/24
1572 | 192.150.228.0/22
1573 | 192.150.232.0/23
1574 | 192.150.238.0/24
1575 | 192.150.248.0/24
1576 | 192.150.252.0/24
1577 | 192.150.254.0/24
1578 | 192.150.58.0/23
1579 | 192.150.60.0/22
1580 | 192.150.64.0/21
1581 | 192.150.72.0/24
1582 | 192.150.75.0/24
1583 | 192.150.76.0/24
1584 | 192.150.78.0/23
1585 | 192.150.80.0/22
1586 | 192.150.84.0/24
1587 | 192.150.89.0/24
1588 | 192.150.92.0/24
1589 | 192.150.94.0/24
1590 | 192.152.111.0/24
1591 | 192.152.112.0/24
1592 | 192.152.122.0/24
1593 | 192.152.124.0/24
1594 | 192.152.14.0/24
1595 | 192.152.141.0/24
1596 | 192.152.151.0/24
1597 | 192.152.156.0/24
1598 | 192.152.166.0/23
1599 | 192.152.17.0/24
1600 | 192.152.174.0/24
1601 | 192.152.184.0/22
1602 | 192.152.241.0/24
1603 | 192.152.244.0/24
1604 | 192.152.253.0/24
1605 | 192.152.254.0/24
1606 | 192.152.26.0/23
1607 | 192.152.42.0/24
1608 | 192.152.44.0/24
1609 | 192.152.47.0/24
1610 | 192.152.48.0/22
1611 | 192.152.54.0/24
1612 | 192.152.6.0/24
1613 | 192.152.61.0/24
1614 | 192.152.62.0/23
1615 | 192.152.68.0/24
1616 | 192.152.82.0/24
1617 | 192.152.98.0/24
1618 | 192.153.116.0/24
1619 | 192.153.127.0/24
1620 | 192.153.13.0/24
1621 | 192.153.153.0/24
1622 | 192.153.166.0/24
1623 | 192.153.168.0/24
1624 | 192.153.171.0/24
1625 | 192.153.173.0/24
1626 | 192.153.174.0/23
1627 | 192.153.176.0/22
1628 | 192.153.18.0/23
1629 | 192.153.180.0/23
1630 | 192.153.182.0/24
1631 | 192.153.188.0/23
1632 | 192.153.194.0/24
1633 | 192.153.2.0/23
1634 | 192.153.213.0/24
1635 | 192.153.89.0/24
1636 | 192.155.1.0/24
1637 | 192.155.2.0/23
1638 | 192.155.4.0/23
1639 | 192.155.6.0/24
1640 | 192.156.132.0/24
1641 | 192.156.162.0/24
1642 | 192.156.167.0/24
1643 | 192.156.210.0/24
1644 | 192.156.213.0/24
1645 | 192.156.217.0/24
1646 | 192.156.227.0/24
1647 | 192.156.239.0/24
1648 | 192.156.248.0/24
1649 | 192.157.1.0/24
1650 | 192.157.129.0/24
1651 | 192.157.16.0/23
1652 | 192.157.165.0/24
1653 | 192.157.166.0/23
1654 | 192.157.168.0/22
1655 | 192.157.172.0/24
1656 | 192.157.174.0/24
1657 | 192.157.176.0/24
1658 | 192.157.185.0/24
1659 | 192.157.187.0/24
1660 | 192.157.189.0/24
1661 | 192.157.2.0/23
1662 | 192.157.8.0/21
1663 | 192.159.100.0/22
1664 | 192.159.105.0/24
1665 | 192.159.108.0/23
1666 | 192.159.118.0/24
1667 | 192.159.121.0/24
1668 | 192.159.122.0/24
1669 | 192.159.70.0/24
1670 | 192.159.73.0/24
1671 | 192.159.77.0/24
1672 | 192.159.84.0/23
1673 | 192.159.90.0/24
1674 | 192.159.95.0/24
1675 | 192.159.99.0/24
1676 | 192.16.123.0/24
1677 | 192.16.124.0/22
1678 | 192.16.128.0/19
1679 | 192.16.160.0/22
1680 | 192.16.164.0/23
1681 | 192.16.166.0/24
1682 | 192.16.183.0/24
1683 | 192.16.184.0/21
1684 | 192.16.192.0/21
1685 | 192.16.200.0/23
1686 | 192.16.202.0/24
1687 | 192.160.10.0/24
1688 | 192.160.109.0/24
1689 | 192.160.110.0/24
1690 | 192.160.123.0/24
1691 | 192.160.126.0/24
1692 | 192.160.142.0/23
1693 | 192.160.15.0/24
1694 | 192.160.152.0/24
1695 | 192.160.156.0/24
1696 | 192.160.160.0/24
1697 | 192.160.172.0/24
1698 | 192.160.177.0/24
1699 | 192.160.178.0/23
1700 | 192.160.194.0/23
1701 | 192.160.21.0/24
1702 | 192.160.22.0/23
1703 | 192.160.224.0/23
1704 | 192.160.231.0/24
1705 | 192.160.232.0/23
1706 | 192.160.245.0/24
1707 | 192.160.246.0/23
1708 | 192.160.248.0/23
1709 | 192.160.251.0/24
1710 | 192.160.252.0/24
1711 | 192.160.27.0/24
1712 | 192.160.33.0/24
1713 | 192.160.37.0/24
1714 | 192.160.65.0/24
1715 | 192.160.67.0/24
1716 | 192.160.95.0/24
1717 | 192.160.96.0/24
1718 | 192.161.64.0/23
1719 | 192.162.0.0/16
1720 | 192.163.128.0/19
1721 | 192.163.32.0/19
1722 | 192.163.64.0/18
1723 | 192.164.0.0/14
1724 | 192.171.1.0/24
1725 | 192.171.128.0/18
1726 | 192.171.192.0/21
1727 | 192.171.2.0/23
1728 | 192.171.4.0/23
1729 | 192.172.253.0/24
1730 | 192.173.1.0/24
1731 | 192.173.128.0/21
1732 | 192.173.2.0/23
1733 | 192.173.4.0/24
1734 | 192.174.64.0/22
1735 | 192.174.68.0/24
1736 | 192.175.32.0/20
1737 | 192.176.0.0/16
1738 | 192.18.195.0/24
1739 | 192.187.16.0/21
1740 | 192.187.24.0/23
1741 | 192.188.10.0/24
1742 | 192.188.105.0/24
1743 | 192.188.116.0/23
1744 | 192.188.121.0/24
1745 | 192.188.122.0/24
1746 | 192.188.125.0/24
1747 | 192.188.127.0/24
1748 | 192.188.129.0/24
1749 | 192.188.132.0/24
1750 | 192.188.136.0/24
1751 | 192.188.145.0/24
1752 | 192.188.157.0/24
1753 | 192.188.158.0/24
1754 | 192.188.187.0/24
1755 | 192.188.189.0/24
1756 | 192.188.233.0/24
1757 | 192.188.234.0/23
1758 | 192.188.236.0/23
1759 | 192.188.242.0/23
1760 | 192.188.244.0/22
1761 | 192.188.63.0/24
1762 | 192.188.64.0/23
1763 | 192.188.69.0/24
1764 | 192.188.96.0/24
1765 | 192.189.1.0/24
1766 | 192.189.119.0/24
1767 | 192.189.14.0/24
1768 | 192.189.151.0/24
1769 | 192.189.154.0/24
1770 | 192.189.157.0/24
1771 | 192.189.160.0/24
1772 | 192.189.166.0/23
1773 | 192.189.168.0/23
1774 | 192.189.170.0/24
1775 | 192.189.202.0/23
1776 | 192.189.23.0/24
1777 | 192.189.251.0/24
1778 | 192.189.41.0/24
1779 | 192.189.51.0/24
1780 | 192.189.52.0/24
1781 | 192.189.55.0/24
1782 | 192.189.66.0/24
1783 | 192.189.69.0/24
1784 | 192.189.70.0/24
1785 | 192.189.73.0/24
1786 | 192.189.76.0/24
1787 | 192.189.8.0/22
1788 | 192.190.129.0/24
1789 | 192.190.130.0/23
1790 | 192.190.132.0/24
1791 | 192.190.173.0/24
1792 | 192.190.174.0/24
1793 | 192.190.182.0/23
1794 | 192.190.190.0/23
1795 | 192.190.192.0/23
1796 | 192.190.201.0/24
1797 | 192.190.202.0/24
1798 | 192.190.233.0/24
1799 | 192.190.234.0/23
1800 | 192.190.236.0/24
1801 | 192.190.240.0/24
1802 | 192.190.242.0/24
1803 | 192.190.247.0/24
1804 | 192.190.248.0/23
1805 | 192.190.44.0/24
1806 | 192.190.58.0/23
1807 | 192.190.64.0/24
1808 | 192.190.67.0/24
1809 | 192.190.69.0/24
1810 | 192.190.95.0/24
1811 | 192.194.0.0/16
1812 | 192.195.1.0/24
1813 | 192.195.105.0/24
1814 | 192.195.106.0/24
1815 | 192.195.110.0/24
1816 | 192.195.116.0/23
1817 | 192.195.118.0/24
1818 | 192.195.134.0/23
1819 | 192.195.136.0/21
1820 | 192.195.144.0/22
1821 | 192.195.148.0/24
1822 | 192.195.183.0/24
1823 | 192.195.184.0/24
1824 | 192.195.195.0/24
1825 | 192.195.236.0/24
1826 | 192.195.42.0/23
1827 | 192.195.72.0/24
1828 | 192.195.8.0/24
1829 | 192.195.98.0/24
1830 | 192.196.1.0/24
1831 | 192.196.128.0/20
1832 | 192.196.144.0/21
1833 | 192.196.152.0/22
1834 | 192.196.16.0/20
1835 | 192.196.2.0/23
1836 | 192.196.32.0/19
1837 | 192.196.4.0/22
1838 | 192.196.64.0/18
1839 | 192.196.8.0/21
1840 | 192.199.16.0/20
1841 | 192.203.108.0/23
1842 | 192.203.227.0/24
1843 | 192.203.80.0/24
1844 | 192.206.222.0/23
1845 | 192.206.224.0/23
1846 | 192.206.226.0/24
1847 | 192.206.77.0/24
1848 | 192.206.78.0/23
1849 | 192.206.80.0/23
1850 | 192.206.86.0/24
1851 | 192.207.14.0/24
1852 | 192.207.141.0/24
1853 | 192.207.142.0/24
1854 | 192.207.196.0/24
1855 | 192.207.31.0/24
1856 | 192.231.67.0/24
1857 | 192.231.82.0/24
1858 | 192.238.1.0/24
1859 | 192.238.10.0/24
1860 | 192.238.2.0/23
1861 | 192.238.4.0/22
1862 | 192.238.8.0/23
1863 | 192.245.152.0/24
1864 | 192.245.169.0/24
1865 | 192.245.225.0/24
1866 | 192.247.1.0/24
1867 | 192.247.10.0/24
1868 | 192.247.2.0/23
1869 | 192.247.4.0/22
1870 | 192.247.8.0/23
1871 | 192.251.226.0/24
1872 | 192.251.61.0/24
1873 | 192.251.62.0/23
1874 | 192.251.64.0/23
1875 | 192.26.105.0/24
1876 | 192.26.106.0/23
1877 | 192.26.108.0/23
1878 | 192.26.111.0/24
1879 | 192.26.112.0/20
1880 | 192.26.128.0/24
1881 | 192.26.133.0/24
1882 | 192.26.134.0/23
1883 | 192.26.154.0/23
1884 | 192.26.156.0/22
1885 | 192.26.160.0/19
1886 | 192.26.192.0/23
1887 | 192.26.231.0/24
1888 | 192.26.234.0/24
1889 | 192.26.236.0/22
1890 | 192.26.28.0/22
1891 | 192.26.32.0/20
1892 | 192.31.102.0/24
1893 | 192.31.14.0/24
1894 | 192.31.166.0/23
1895 | 192.31.168.0/22
1896 | 192.31.211.0/24
1897 | 192.31.23.0/24
1898 | 192.31.231.0/24
1899 | 192.31.252.0/24
1900 | 192.31.26.0/23
1901 | 192.31.31.0/24
1902 | 192.31.40.0/24
1903 | 192.31.62.0/24
1904 | 192.33.113.0/24
1905 | 192.33.114.0/24
1906 | 192.33.118.0/23
1907 | 192.33.120.0/21
1908 | 192.33.130.0/23
1909 | 192.33.143.0/24
1910 | 192.33.144.0/23
1911 | 192.33.147.0/24
1912 | 192.33.148.0/22
1913 | 192.33.15.0/24
1914 | 192.33.152.0/21
1915 | 192.33.16.0/24
1916 | 192.33.160.0/22
1917 | 192.33.164.0/23
1918 | 192.33.166.0/24
1919 | 192.33.169.0/24
1920 | 192.33.170.0/23
1921 | 192.33.176.0/22
1922 | 192.33.180.0/23
1923 | 192.33.182.0/24
1924 | 192.33.192.0/19
1925 | 192.33.224.0/21
1926 | 192.33.254.0/24
1927 | 192.33.36.0/24
1928 | 192.33.87.0/24
1929 | 192.33.88.0/21
1930 | 192.33.96.0/20
1931 | 192.34.107.0/24
1932 | 192.34.116.0/24
1933 | 192.34.179.0/24
1934 | 192.34.19.0/24
1935 | 192.34.50.0/24
1936 | 192.35.0.0/20
1937 | 192.35.108.0/24
1938 | 192.35.138.0/24
1939 | 192.35.146.0/24
1940 | 192.35.149.0/24
1941 | 192.35.150.0/23
1942 | 192.35.152.0/23
1943 | 192.35.16.0/22
1944 | 192.35.172.0/24
1945 | 192.35.183.0/24
1946 | 192.35.184.0/21
1947 | 192.35.192.0/24
1948 | 192.35.197.0/24
1949 | 192.35.198.0/24
1950 | 192.35.205.0/24
1951 | 192.35.206.0/23
1952 | 192.35.229.0/24
1953 | 192.35.240.0/22
1954 | 192.35.244.0/24
1955 | 192.35.246.0/23
1956 | 192.35.63.0/24
1957 | 192.35.64.0/21
1958 | 192.35.72.0/24
1959 | 192.35.90.0/24
1960 | 192.35.94.0/24
1961 | 192.36.0.0/15
1962 | 192.38.0.0/16
1963 | 192.40.228.0/24
1964 | 192.40.69.0/24
1965 | 192.40.70.0/23
1966 | 192.40.72.0/21
1967 | 192.40.80.0/24
1968 | 192.41.103.0/24
1969 | 192.41.104.0/21
1970 | 192.41.112.0/20
1971 | 192.41.128.0/21
1972 | 192.41.136.0/24
1973 | 192.41.140.0/22
1974 | 192.41.144.0/23
1975 | 192.41.147.0/24
1976 | 192.41.149.0/24
1977 | 192.41.150.0/23
1978 | 192.41.152.0/21
1979 | 192.41.160.0/24
1980 | 192.41.210.0/24
1981 | 192.41.216.0/24
1982 | 192.41.218.0/24
1983 | 192.41.227.0/24
1984 | 192.42.1.0/24
1985 | 192.42.100.0/24
1986 | 192.42.102.0/24
1987 | 192.42.113.0/24
1988 | 192.42.114.0/23
1989 | 192.42.116.0/22
1990 | 192.42.120.0/21
1991 | 192.42.128.0/22
1992 | 192.42.132.0/24
1993 | 192.42.143.0/24
1994 | 192.42.180.0/22
1995 | 192.42.184.0/21
1996 | 192.42.192.0/21
1997 | 192.42.200.0/23
1998 | 192.42.253.0/24
1999 | 192.42.42.0/23
2000 | 192.42.44.0/22
2001 | 192.42.53.0/24
2002 | 192.42.63.0/24
2003 | 192.42.64.0/24
2004 | 192.42.87.0/24
2005 | 192.43.162.0/23
2006 | 192.43.164.0/22
2007 | 192.43.168.0/22
2008 | 192.43.192.0/22
2009 | 192.43.196.0/24
2010 | 192.43.210.0/24
2011 | 192.43.212.0/24
2012 | 192.43.234.0/24
2013 | 192.44.0.0/18
2014 | 192.44.240.0/21
2015 | 192.44.248.0/22
2016 | 192.44.64.0/22
2017 | 192.44.71.0/24
2018 | 192.44.72.0/21
2019 | 192.44.80.0/21
2020 | 192.44.88.0/23
2021 | 192.44.90.0/24
2022 | 192.47.244.0/22
2023 | 192.47.248.0/23
2024 | 192.48.107.0/24
2025 | 192.48.145.0/24
2026 | 192.48.224.0/24
2027 | 192.48.231.0/24
2028 | 192.48.31.0/24
2029 | 192.49.0.0/16
2030 | 192.5.142.0/24
2031 | 192.5.145.0/24
2032 | 192.5.162.0/24
2033 | 192.5.239.0/24
2034 | 192.5.254.0/24
2035 | 192.5.28.0/23
2036 | 192.5.30.0/24
2037 | 192.5.36.0/24
2038 | 192.5.50.0/24
2039 | 192.5.59.0/24
2040 | 192.5.61.0/24
2041 | 192.5.62.0/24
2042 | 192.5.97.0/24
2043 | 192.51.0.0/20
2044 | 192.52.0.0/19
2045 | 192.52.152.0/24
2046 | 192.52.159.0/24
2047 | 192.52.160.0/23
2048 | 192.52.221.0/24
2049 | 192.52.222.0/23
2050 | 192.52.253.0/24
2051 | 192.52.254.0/24
2052 | 192.52.32.0/20
2053 | 192.52.48.0/23
2054 | 192.52.50.0/24
2055 | 192.53.103.0/24
2056 | 192.53.104.0/24
2057 | 192.54.104.0/24
2058 | 192.54.113.0/24
2059 | 192.54.115.0/24
2060 | 192.54.116.0/22
2061 | 192.54.120.0/24
2062 | 192.54.122.0/24
2063 | 192.54.125.0/24
2064 | 192.54.126.0/23
2065 | 192.54.128.0/24
2066 | 192.54.132.0/24
2067 | 192.54.139.0/24
2068 | 192.54.141.0/24
2069 | 192.54.142.0/23
2070 | 192.54.144.0/20
2071 | 192.54.160.0/19
2072 | 192.54.192.0/20
2073 | 192.54.208.0/21
2074 | 192.54.216.0/22
2075 | 192.54.220.0/23
2076 | 192.54.225.0/24
2077 | 192.54.245.0/24
2078 | 192.54.254.0/24
2079 | 192.54.31.0/24
2080 | 192.54.32.0/20
2081 | 192.54.48.0/22
2082 | 192.54.52.0/24
2083 | 192.54.54.0/23
2084 | 192.54.56.0/21
2085 | 192.54.64.0/20
2086 | 192.54.80.0/24
2087 | 192.55.101.0/24
2088 | 192.55.105.0/24
2089 | 192.55.109.0/24
2090 | 192.55.115.0/24
2091 | 192.55.129.0/24
2092 | 192.55.132.0/24
2093 | 192.55.188.0/24
2094 | 192.55.193.0/24
2095 | 192.55.197.0/24
2096 | 192.55.212.0/24
2097 | 192.55.244.0/24
2098 | 192.55.84.0/24
2099 | 192.55.89.0/24
2100 | 192.58.197.0/24
2101 | 192.58.218.0/24
2102 | 192.58.28.0/22
2103 | 192.58.32.0/22
2104 | 192.58.41.0/24
2105 | 192.58.42.0/23
2106 | 192.58.44.0/22
2107 | 192.58.48.0/20
2108 | 192.58.64.0/20
2109 | 192.58.80.0/21
2110 | 192.58.88.0/23
2111 | 192.64.100.0/22
2112 | 192.64.125.0/24
2113 | 192.64.202.0/24
2114 | 192.64.28.0/24
2115 | 192.64.44.0/23
2116 | 192.65.131.0/24
2117 | 192.65.132.0/24
2118 | 192.65.139.0/24
2119 | 192.65.144.0/23
2120 | 192.65.146.0/24
2121 | 192.65.153.0/24
2122 | 192.65.183.0/24
2123 | 192.65.184.0/21
2124 | 192.65.192.0/22
2125 | 192.65.196.0/23
2126 | 192.65.219.0/24
2127 | 192.65.220.0/22
2128 | 192.65.224.0/22
2129 | 192.65.228.0/24
2130 | 192.65.51.0/24
2131 | 192.65.52.0/22
2132 | 192.65.56.0/21
2133 | 192.65.64.0/22
2134 | 192.65.68.0/23
2135 | 192.65.70.0/24
2136 | 192.65.92.0/23
2137 | 192.65.94.0/24
2138 | 192.65.96.0/24
2139 | 192.66.0.0/16
2140 | 192.67.100.0/22
2141 | 192.67.104.0/24
2142 | 192.67.135.0/24
2143 | 192.67.167.0/24
2144 | 192.67.170.0/24
2145 | 192.67.189.0/24
2146 | 192.67.190.0/23
2147 | 192.67.192.0/20
2148 | 192.67.208.0/24
2149 | 192.67.218.0/24
2150 | 192.67.220.0/23
2151 | 192.67.223.0/24
2152 | 192.67.249.0/24
2153 | 192.67.3.0/24
2154 | 192.67.39.0/24
2155 | 192.67.4.0/24
2156 | 192.67.43.0/24
2157 | 192.67.47.0/24
2158 | 192.67.50.0/24
2159 | 192.67.52.0/24
2160 | 192.67.55.0/24
2161 | 192.67.58.0/24
2162 | 192.67.76.0/24
2163 | 192.67.79.0/24
2164 | 192.67.87.0/24
2165 | 192.67.94.0/24
2166 | 192.68.0.0/20
2167 | 192.68.104.0/22
2168 | 192.68.151.0/24
2169 | 192.68.152.0/23
2170 | 192.68.16.0/22
2171 | 192.68.165.0/24
2172 | 192.68.166.0/23
2173 | 192.68.168.0/23
2174 | 192.68.170.0/24
2175 | 192.68.174.0/24
2176 | 192.68.176.0/24
2177 | 192.68.182.0/24
2178 | 192.68.186.0/24
2179 | 192.68.209.0/24
2180 | 192.68.211.0/24
2181 | 192.68.212.0/22
2182 | 192.68.216.0/24
2183 | 192.68.221.0/24
2184 | 192.68.224.0/24
2185 | 192.68.23.0/24
2186 | 192.68.230.0/24
2187 | 192.68.250.0/23
2188 | 192.68.252.0/24
2189 | 192.68.254.0/24
2190 | 192.68.31.0/24
2191 | 192.68.32.0/20
2192 | 192.68.48.0/22
2193 | 192.68.76.0/22
2194 | 192.68.80.0/20
2195 | 192.68.96.0/21
2196 | 192.70.0.0/18
2197 | 192.70.112.0/21
2198 | 192.70.133.0/24
2199 | 192.70.134.0/24
2200 | 192.70.136.0/24
2201 | 192.70.140.0/22
2202 | 192.70.144.0/20
2203 | 192.70.242.0/24
2204 | 192.70.64.0/19
2205 | 192.70.96.0/20
2206 | 192.71.0.0/16
2207 | 192.73.19.0/24
2208 | 192.73.20.0/24
2209 | 192.73.226.0/24
2210 | 192.73.229.0/24
2211 | 192.73.34.0/23
2212 | 192.73.36.0/22
2213 | 192.73.40.0/22
2214 | 192.73.44.0/24
2215 | 192.76.123.0/24
2216 | 192.76.124.0/22
2217 | 192.76.128.0/22
2218 | 192.76.132.0/24
2219 | 192.76.134.0/23
2220 | 192.76.136.0/21
2221 | 192.76.144.0/20
2222 | 192.76.16.0/20
2223 | 192.76.160.0/21
2224 | 192.76.168.0/22
2225 | 192.76.172.0/24
2226 | 192.76.176.0/24
2227 | 192.76.241.0/24
2228 | 192.76.242.0/23
2229 | 192.76.244.0/22
2230 | 192.76.248.0/24
2231 | 192.76.32.0/22
2232 | 192.76.6.0/23
2233 | 192.76.8.0/21
2234 | 192.77.11.0/24
2235 | 192.77.114.0/23
2236 | 192.77.120.0/22
2237 | 192.77.132.0/22
2238 | 192.77.136.0/23
2239 | 192.77.138.0/24
2240 | 192.77.140.0/23
2241 | 192.80.20.0/23
2242 | 192.80.31.0/24
2243 | 192.80.32.0/21
2244 | 192.80.40.0/23
2245 | 192.80.42.0/24
2246 | 192.80.46.0/24
2247 | 192.80.51.0/24
2248 | 192.81.109.0/24
2249 | 192.81.121.0/24
2250 | 192.81.123.0/24
2251 | 192.81.160.0/24
2252 | 192.81.182.0/23
2253 | 192.81.184.0/24
2254 | 192.81.194.0/24
2255 | 192.81.230.0/24
2256 | 192.81.234.0/24
2257 | 192.81.59.0/24
2258 | 192.81.61.0/24
2259 | 192.81.62.0/24
2260 | 192.82.121.0/24
2261 | 192.82.124.0/24
2262 | 192.82.127.0/24
2263 | 192.82.153.0/24
2264 | 192.82.157.0/24
2265 | 192.82.158.0/24
2266 | 192.82.214.0/24
2267 | 192.82.220.0/23
2268 | 192.82.241.0/24
2269 | 192.83.0.0/18
2270 | 192.83.100.0/24
2271 | 192.83.102.0/24
2272 | 192.83.160.0/24
2273 | 192.83.165.0/24
2274 | 192.83.200.0/24
2275 | 192.83.202.0/24
2276 | 192.83.223.0/24
2277 | 192.83.229.0/24
2278 | 192.83.64.0/19
2279 | 192.83.96.0/22
2280 | 192.84.101.0/24
2281 | 192.84.102.0/23
2282 | 192.84.104.0/22
2283 | 192.84.108.0/23
2284 | 192.84.127.0/24
2285 | 192.84.128.0/20
2286 | 192.84.13.0/24
2287 | 192.84.144.0/21
2288 | 192.84.15.0/24
2289 | 192.84.152.0/22
2290 | 192.84.156.0/24
2291 | 192.84.166.0/24
2292 | 192.84.173.0/24
2293 | 192.84.176.0/20
2294 | 192.84.192.0/20
2295 | 192.84.212.0/24
2296 | 192.84.220.0/23
2297 | 192.84.226.0/23
2298 | 192.84.228.0/23
2299 | 192.84.245.0/24
2300 | 192.84.246.0/23
2301 | 192.84.27.0/24
2302 | 192.84.30.0/24
2303 | 192.84.32.0/23
2304 | 192.84.5.0/24
2305 | 192.84.62.0/24
2306 | 192.84.75.0/24
2307 | 192.84.76.0/22
2308 | 192.84.80.0/22
2309 | 192.84.84.0/24
2310 | 192.84.87.0/24
2311 | 192.84.90.0/23
2312 | 192.84.92.0/22
2313 | 192.84.96.0/22
2314 | 192.86.11.0/24
2315 | 192.86.125.0/24
2316 | 192.86.126.0/23
2317 | 192.86.134.0/24
2318 | 192.86.137.0/24
2319 | 192.86.138.0/24
2320 | 192.86.14.0/24
2321 | 192.86.163.0/24
2322 | 192.86.166.0/23
2323 | 192.86.169.0/24
2324 | 192.86.18.0/24
2325 | 192.86.25.0/24
2326 | 192.86.254.0/24
2327 | 192.86.27.0/24
2328 | 192.86.89.0/24
2329 | 192.87.0.0/16
2330 | 192.88.1.0/24
2331 | 192.88.10.0/24
2332 | 192.88.108.0/24
2333 | 192.88.118.0/24
2334 | 192.88.123.0/24
2335 | 192.88.128.0/24
2336 | 192.88.130.0/24
2337 | 192.88.133.0/24
2338 | 192.88.17.0/24
2339 | 192.88.196.0/24
2340 | 192.88.204.0/24
2341 | 192.88.23.0/24
2342 | 192.88.238.0/23
2343 | 192.88.24.0/24
2344 | 192.88.250.0/23
2345 | 192.88.252.0/23
2346 | 192.88.254.0/24
2347 | 192.88.4.0/24
2348 | 192.88.83.0/24
2349 | 192.88.84.0/24
2350 | 192.88.86.0/24
2351 | 192.88.9.0/24
2352 | 192.88.97.0/24
2353 | 192.88.98.0/24
2354 | 192.89.0.0/16
2355 | 192.91.140.0/23
2356 | 192.91.177.0/24
2357 | 192.91.186.0/24
2358 | 192.91.189.0/24
2359 | 192.91.191.0/24
2360 | 192.91.199.0/24
2361 | 192.91.201.0/24
2362 | 192.91.211.0/24
2363 | 192.91.214.0/23
2364 | 192.91.216.0/21
2365 | 192.91.224.0/21
2366 | 192.91.232.0/23
2367 | 192.91.236.0/22
2368 | 192.91.240.0/21
2369 | 192.92.104.0/23
2370 | 192.92.106.0/24
2371 | 192.92.108.0/23
2372 | 192.92.116.0/24
2373 | 192.92.125.0/24
2374 | 192.92.126.0/23
2375 | 192.92.128.0/21
2376 | 192.92.136.0/22
2377 | 192.92.141.0/24
2378 | 192.92.142.0/23
2379 | 192.92.144.0/21
2380 | 192.92.152.0/23
2381 | 192.92.155.0/24
2382 | 192.92.156.0/24
2383 | 192.92.216.0/24
2384 | 192.92.86.0/24
2385 | 192.92.94.0/24
2386 | 192.93.0.0/16
2387 | 192.94.111.0/24
2388 | 192.94.112.0/22
2389 | 192.94.116.0/23
2390 | 192.94.156.0/22
2391 | 192.94.160.0/22
2392 | 192.94.172.0/24
2393 | 192.94.175.0/24
2394 | 192.94.176.0/20
2395 | 192.94.192.0/21
2396 | 192.94.212.0/24
2397 | 192.94.221.0/24
2398 | 192.94.226.0/24
2399 | 192.94.233.0/24
2400 | 192.94.235.0/24
2401 | 192.94.239.0/24
2402 | 192.94.24.0/24
2403 | 192.94.28.0/24
2404 | 192.94.57.0/24
2405 | 192.94.58.0/24
2406 | 192.94.67.0/24
2407 | 192.94.68.0/24
2408 | 192.94.76.0/24
2409 | 192.98.0.0/16
2410 | 193.0.0.0/8
2411 | 194.0.0.0/7
2412 | 196.1.3.0/24
2413 | 196.1.5.0/24
2414 | 196.1.6.0/24
2415 | 196.1.64.0/22
2416 | 196.1.69.0/24
2417 | 196.1.70.0/24
2418 | 196.15.32.0/19
2419 | 196.2.4.0/22
2420 | 196.3.66.0/23
2421 | 196.3.68.0/22
2422 | 196.3.91.0/24
2423 | 198.11.0.0/22
2424 | 198.133.140.0/24
2425 | 198.133.226.0/24
2426 | 198.133.80.0/22
2427 | 198.133.84.0/23
2428 | 198.135.137.0/24
2429 | 198.135.138.0/24
2430 | 198.135.167.0/24
2431 | 198.147.160.0/24
2432 | 198.148.177.0/24
2433 | 198.148.178.0/24
2434 | 198.17.117.0/24
2435 | 198.17.180.0/23
2436 | 198.17.182.0/24
2437 | 198.17.77.0/24
2438 | 198.206.197.0/24
2439 | 198.206.200.0/23
2440 | 198.206.202.0/24
2441 | 198.22.51.0/24
2442 | 198.22.93.0/24
2443 | 198.22.94.0/23
2444 | 198.22.96.0/23
2445 | 198.240.128.0/17
2446 | 198.36.32.0/21
2447 | 198.36.40.0/22
2448 | 198.36.44.0/23
2449 | 198.36.46.0/24
2450 | 198.51.12.0/24
2451 | 198.51.143.0/24
2452 | 198.51.144.0/23
2453 | 198.51.146.0/24
2454 | 198.99.148.0/24
2455 | 198.99.222.0/24
2456 | 199.43.246.0/23
2457 | 199.53.0.0/16
2458 | 199.91.16.0/20
2459 | 212.0.0.0/7
2460 | 217.0.0.0/8
2461 | 2001:600::/23
2462 | 2001:800::/22
2463 | 2001:1400::/22
2464 | 2001:1a00::/23
2465 | 2001:1c00::/22
2466 | 2001:2000::/20
2467 | 2001:3000::/21
2468 | 2001:3800::/22
2469 | 2001:4000::/23
2470 | 2001:4600::/23
2471 | 2001:4800::/22
2472 | 2001:4c00::/23
2473 | 2001:5000::/20
2474 | 2003::/18
2475 | 2a00::/12
2476 |
--------------------------------------------------------------------------------
/data/schema.sql:
--------------------------------------------------------------------------------
1 | -- Database scheme for IRRExplorer
2 | -- Tied to PostgreSQL due to use of cidr type and gist indexing,
3 | -- to effeciently query routes.
4 | --
5 | -- Requires PostgreSQL 9.4 (gist indexing of cidr/inet)
6 |
7 |
8 | CREATE TABLE sources (
9 | id serial NOT NULL PRIMARY KEY,
10 | name text UNIQUE NOT NULL,
11 | last_seen_serial integer
12 | );
13 |
14 | CREATE TABLE managed_routes (
15 | route cidr NOT NULL,
16 | source_id integer NOT NULL REFERENCES sources(id)
17 | );
18 |
19 |
20 | CREATE VIEW managed_routes_view AS
21 | SELECT
22 | route, name AS source
23 | FROM
24 | managed_routes LEFT OUTER JOIN sources ON (managed_routes.source_id = sources.id);
25 |
26 |
27 | -- consider expanding this with start/end timestamp later
28 | CREATE TABLE routes (
29 | route cidr NOT NULL,
30 | asn bigint NOT NULL,
31 | source_id integer NOT NULL REFERENCES sources(id),
32 |
33 | -- The unique constraint may not be the best from an efficiancy point of view,
34 | -- but having duplicates is likely to cause weird results
35 | CONSTRAINT unique_entry UNIQUE (route, asn, source_id),
36 | CONSTRAINT positive_asn CHECK (asn >= 0)
37 | );
38 |
39 | -- CREATE INDEX route_gist ON routes USING gist (route inet_ops);
40 |
41 | -- Index for routes. This performs a lot better than the inet_ops gist index
42 |
43 | CREATE TYPE inetrange AS range (subtype = inet);
44 |
45 | CREATE FUNCTION cidr_to_range(cidr) returns inetrange language sql AS 'select inetrange(set_masklen($1::inet, 0), set_masklen(broadcast($1), 0))';
46 |
47 | CREATE INDEX ON routes USING gist ((cidr_to_range(route)));
48 |
49 |
50 | CREATE VIEW routes_view AS
51 | SELECT
52 | route, asn, name AS source
53 | FROM routes LEFT OUTER JOIN sources ON (routes.source_id = sources.id);
54 |
55 |
56 | CREATE TABLE as_sets (
57 | as_macro text NOT NULL,
58 | members text[] NOT NULL,
59 | source_id integer NOT NULL REFERENCES sources(id),
60 |
61 | CONSTRAINT unique_macro_source UNIQUE (as_macro, source_id)
62 | );
63 |
64 |
65 | CREATE VIEW as_sets_view AS
66 | SELECT
67 | as_macro, members, name AS source
68 | FROM as_sets LEFT OUTER JOIN sources ON (as_sets.source_id = sources.id);
69 |
70 |
71 |
72 | CREATE OR REPLACE FUNCTION create_managed_route (
73 | in_route cidr,
74 | in_source varchar
75 | )
76 | RETURNS integer AS $inserted$
77 |
78 | DECLARE
79 | source_id integer;
80 | result integer;
81 | BEGIN
82 | -- check if we have source, create if not
83 | SELECT sources.id INTO source_id FROM sources WHERE name = in_source;
84 | IF NOT FOUND THEN
85 | INSERT INTO sources (name) VALUES (in_source) RETURNING id INTO source_id;
86 | END IF;
87 |
88 | INSERT INTO managed_routes (route, source_id) VALUES (in_route, source_id);
89 |
90 | result = 1;
91 | return result;
92 | END;
93 | $inserted$
94 | LANGUAGE plpgsql;
95 |
96 |
97 | CREATE OR REPLACE FUNCTION create_route (
98 | in_route cidr,
99 | in_asn bigint,
100 | in_source varchar
101 | )
102 | RETURNS integer AS $inserted$
103 |
104 | DECLARE
105 | source_id integer;
106 | result integer;
107 | BEGIN
108 | -- check if we have source, create if not
109 | SELECT sources.id INTO source_id FROM sources WHERE name = in_source;
110 | IF NOT FOUND THEN
111 | INSERT INTO sources (name) VALUES (in_source) RETURNING id INTO source_id;
112 | END IF;
113 |
114 | INSERT INTO routes (route, asn, source_id) VALUES (in_route, in_asn, source_id)
115 | ON CONFLICT DO NOTHING;
116 |
117 | result = 1;
118 | return result;
119 | END;
120 | $inserted$
121 | LANGUAGE plpgsql;
122 |
123 |
124 |
125 | CREATE OR REPLACE FUNCTION create_as_set (
126 | in_as_macro text,
127 | in_members text[],
128 | in_source varchar
129 | )
130 | RETURNS integer AS $inserted$
131 |
132 | DECLARE
133 | source_id integer;
134 | result integer;
135 | BEGIN
136 | -- check if we have source, create if not
137 | SELECT sources.id INTO source_id FROM sources WHERE name = in_source;
138 | IF NOT FOUND THEN
139 | INSERT INTO sources (name) VALUES (in_source) RETURNING id INTO source_id;
140 | END IF;
141 |
142 | INSERT INTO as_sets (as_macro, members, source_id) VALUES (in_as_macro, in_members, source_id)
143 | ON CONFLICT ON CONSTRAINT unique_macro_source DO UPDATE SET members = in_members;
144 |
145 | result = 1;
146 | return result;
147 | END;
148 | $inserted$
149 | LANGUAGE plpgsql;
150 |
151 |
--------------------------------------------------------------------------------
/db/README:
--------------------------------------------------------------------------------
1 | How to setup to initally setup postgres and load data into it.
2 |
3 | From the db directory, run
4 |
5 | ./boostrap
6 |
7 | And that should be it :-)
8 |
9 | Copy ../irrexplorer_config.yml.dist to ../irrexplorer_config.yml and fill it with the sources you want first though.
10 |
11 | Read bootstrap if you are interested in the details :-)
12 |
13 |
--------------------------------------------------------------------------------
/db/bootstrap:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -ev
4 |
5 | # Bootstrap script for IRRExplorer PostgreSQL database
6 |
7 | # Create database
8 | echo "Please input sudo password to create irrexplorer database (or do it manually)"
9 | #sudo su - postgres -c "createdb irrexplorer"
10 | psql irrexplorer -f ../data/schema.sql
11 |
12 |
13 | # Fetch irr databases
14 | ./fetch ../irrexplorer_config.yml
15 |
16 | # Create sources
17 | for x in *.db*.gz ; do echo $x|cut -f1 -d'.' ;done|sort|uniq| ./create_source > sources.sql
18 | echo "bgp" | ./create_source >> sources.sql
19 |
20 | # Insert sources and create map
21 | psql irrexplorer -f sources.sql
22 | psql irrexplorer -c "select name,id from sources;" -tAF, > sources.map
23 |
24 | # Create routes and as-set data files, filter double repeated routes
25 | # zcatting and processing this twice is sorta silly
26 | zcat *.db*.gz | ./create_irr_routes | uniq -u > irr_routes.data
27 | zcat *.db*.gz | ./create_irr_as_sets > irr_as_sets.data
28 |
29 | # BGP route table dump
30 | curl http://lg01.infra.ring.nlnog.net/table.txt | ./create_bgp > bgp.data
31 |
32 | # Create serial
33 | ./create_serials > serials.sql
34 |
35 | # And the ripe managed space
36 | ./create_managed ripe < ../data/ripe-managed-space.txt > ripe_managed.sql
37 |
38 | # RFC managed / reserved ip space
39 | ./create_managed < ../data/rfc-managed.txt > rfc_managed.sql
40 |
41 | # Load data in postgres
42 |
43 | psql irrexplorer -f ripe_managed.sql
44 | psql irrexplorer -f rfc_managed.sql
45 | psql irrexplorer -f serials.sql
46 |
47 | psql irrexplorer -c "\copy routes from irr_routes.data delimiter '|'"
48 | psql irrexplorer -c "\copy as_sets from irr_as_sets.data delimiter '|'"
49 | psql irrexplorer -c "\copy routes from bgp.data delimiter '|'"
50 |
51 | rm *.gz *.CURRENTSERIAL
52 |
--------------------------------------------------------------------------------
/db/create_bgp:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import sys
4 | import sources
5 |
6 | bgp_id = sources.getSourceMap()['bgp']
7 |
8 |
9 | def main():
10 |
11 | for line in sys.stdin:
12 |
13 | route, origin = line.strip().split(' ',1)
14 | print '%s|%s|%s' % (route, origin, bgp_id)
15 |
16 |
17 | if __name__ == '__main__':
18 | main()
19 |
20 |
--------------------------------------------------------------------------------
/db/create_irr_as_sets:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import fileinput
4 | import sys
5 |
6 |
7 | def main():
8 |
9 | import irrparser
10 |
11 | sources = {}
12 | for line in open('sources.map').readlines():
13 | source, id_ = line.strip().split(',')
14 | sources[source] = id_
15 |
16 | object_data = []
17 | for line in fileinput.input():
18 | if not line == '\n':
19 | object_data.append(line)
20 | else:
21 | obj, values = irrparser.irrParser(object_data)
22 | object_data = []
23 |
24 | if obj == irrparser.AS_SET:
25 | members = '{' + ','.join(values[1]) + '}'
26 |
27 | source = sources.get(values[2])
28 | if source is None:
29 | print >> sys.stderr, 'No source for object: ', values[0], members
30 | continue
31 |
32 | fields = (values[0], members, source )
33 | print '|'.join(fields)
34 |
35 |
36 | if __name__ == '__main__':
37 | sys.path.insert(0, '../irrexplorer') # hack on :-)
38 | main()
39 |
--------------------------------------------------------------------------------
/db/create_irr_routes:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import fileinput
4 | import sys
5 | import ipaddr
6 |
7 |
8 | def main():
9 |
10 | import irrparser
11 |
12 | sources = {}
13 | for line in open('sources.map').readlines():
14 | source, id_ = line.strip().split(',')
15 | sources[source] = id_
16 |
17 | object_data = []
18 | for line in fileinput.input():
19 | if not line == '\n':
20 | object_data.append(line)
21 | else:
22 | obj, values = irrparser.irrParser(object_data)
23 | object_data = []
24 |
25 | if obj == irrparser.ROUTE:
26 | try:
27 | ipaddr.IPNetwork(values[0], strict=True)
28 | except ValueError as e:
29 | if 'does not appear to be' in str(e):
30 | pass # usually leading zero in v4 octets, we can handle those
31 | else:
32 | print >> sys.stderr, str(e), 'source: ', values[2]
33 | continue
34 |
35 | source = sources.get(values[2])
36 | if source is None:
37 | print >> sys.stderr, 'No source for object: ', values[0], values[1]
38 | continue
39 |
40 | fields = ( values[0], str(values[1]), source )
41 | print '|'.join(fields)
42 |
43 |
44 | if __name__ == '__main__':
45 | sys.path.insert(0, '../irrexplorer') # hack on :-)
46 | main()
47 |
--------------------------------------------------------------------------------
/db/create_managed:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import sys
4 |
5 | INSERT = "SELECT create_managed_route ('%s', '%s');"
6 |
7 | default_source = sys.argv[1] if len(sys.argv) >= 2 else None
8 |
9 | print 'BEGIN;'
10 | for line in sys.stdin:
11 |
12 | line = line.strip()
13 | if ' ' in line:
14 | prefix, source = line.strip().split(' ',1)
15 | source = source.strip() or default_source
16 | else:
17 | prefix = line
18 | source = default_source
19 |
20 | print INSERT % (prefix, source)
21 |
22 | print 'COMMIT;'
23 |
24 |
--------------------------------------------------------------------------------
/db/create_serials:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import os
4 |
5 |
6 | UPDATE_SERIAL = "UPDATE sources SET last_seen_serial = %s WHERE sources.name = '%s';"
7 |
8 |
9 | for file_ in os.listdir(os.getcwd()):
10 |
11 | if file_.endswith('.CURRENTSERIAL'):
12 |
13 | serial = open(file_).read().strip()
14 | source = file_.split('.')[0].lower()
15 |
16 | print UPDATE_SERIAL % (serial, source)
17 |
18 |
--------------------------------------------------------------------------------
/db/create_source:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import sys
4 |
5 |
6 | CREATE_SOURCE = "INSERT INTO sources (name) VALUES ('%s');"
7 |
8 |
9 | for line in sys.stdin.readlines():
10 | print CREATE_SOURCE % line.strip()
11 |
12 |
--------------------------------------------------------------------------------
/db/fetch:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # Tool to fetch databases from irrexplorer yaml config file
4 |
5 | import sys
6 | import subprocess
7 | import yaml
8 |
9 | def fetch(url):
10 | file_name = url.split('/')[-1]
11 | print 'Fetching %s --> %s' % (url, file_name)
12 | args = ['wget', '-4', '-q', '-O', file_name, url]
13 | wget = subprocess.Popen(args)
14 | wget.wait()
15 |
16 | def main():
17 |
18 | if len(sys.argv) == 1:
19 | print 'No argument(s) given'
20 | print 'Usage: ./fetch < yaml_config_file > [ database ]'
21 | sys.exit(1)
22 |
23 | yml_cfg = sys.argv[1]
24 | cfg = yaml.load(open(yml_cfg))
25 |
26 | if not 'databases' in cfg:
27 | print 'No database in %s' % yml_cfg
28 | sys.exit(2)
29 |
30 | for db in cfg['databases']:
31 | for db_name, db_info in db.items():
32 | if len(sys.argv) == 3:
33 | if not db_name == sys.argv[2]:
34 | continue
35 | for dbe in db_info:
36 | for dbk, dbv in dbe.items():
37 | if dbk in ('serial', 'dump'):
38 | if isinstance(dbv, list):
39 | for i in dbv:
40 | fetch(i)
41 | else:
42 | fetch(dbv)
43 |
44 |
45 | if __name__ == '__main__':
46 | main()
47 |
--------------------------------------------------------------------------------
/db/refresh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -evx
4 |
5 | # Fetch irr databases
6 | ./fetch ../irrexplorer_config.yml $1
7 |
8 | # Insert sources and create map
9 | psql irrexplorer -c "select name,id from sources where name = '$1';" -tAF, > sources.map
10 |
11 | # Create routes and as-set data files, filter double repeated routes
12 | # zcatting and processing this twice is sorta silly
13 | zcat *.db*.gz | tee >(./create_irr_routes | sort -u > irr_routes.data) | ./create_irr_as_sets > irr_as_sets.data
14 |
15 | # Create serial
16 | ./create_serials > serials.sql
17 |
18 | # Load data in postgres
19 | psql irrexplorer -f serials.sql
20 |
21 | set +e
22 | psql irrexplorer -c "DELETE FROM routes USING sources WHERE routes.source_id = sources.id AND sources.name = '$1';"
23 | psql irrexplorer -c "DELETE FROM as_sets USING sources WHERE as_sets.source_id = sources.id AND sources.name = '$1';"
24 |
25 | psql irrexplorer -c "\copy routes from irr_routes.data delimiter '|'"
26 | psql irrexplorer -c "\copy as_sets from irr_as_sets.data delimiter '|'"
27 |
28 | set -e
29 |
30 | rm -fv *.gz *.CURRENTSERIAL
31 |
--------------------------------------------------------------------------------
/db/refresh_ripe_managed:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -ev
4 |
5 | source_id=$(psql irrexplorer -c "select id from sources where name = 'ripe';" -tAF,)
6 |
7 | ../fetch_ripe_managed.py | sed "s/$/|${source_id}/" > ripe_managed.data
8 |
9 | psql irrexplorer -c "DELETE FROM managed_routes WHERE source_id = '${source_id}';"
10 | psql irrexplorer -c "\copy managed_routes from ripe_managed.data delimiter '|'"
11 | rm ripe_managed.data
12 |
--------------------------------------------------------------------------------
/db/sources.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | def getSourceMap():
4 |
5 | sources = {}
6 | for line in open('sources.map').readlines():
7 | source, id_ = line.strip().split(',')
8 | sources[source] = id_
9 |
10 | return sources
11 |
12 |
13 | if __name__ == '__main__':
14 | for k,v in getSourceMap().items():
15 | print k,v
16 |
17 |
--------------------------------------------------------------------------------
/docs/irrexplorer-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/job/irrexplorer/0af6f13b6b81d6dc66e8a1015ec428773d08c17d/docs/irrexplorer-logo.png
--------------------------------------------------------------------------------
/exabgp.conf:
--------------------------------------------------------------------------------
1 | neighbor 165.254.255.1 {
2 | description "full feed";
3 | router-id 192.168.127.1;
4 | local-address 37.77.58.22;
5 | local-as 15562;
6 | peer-as 15562;
7 | graceful-restart;
8 | process testlockdown {
9 | encoder json;
10 | run /usr/local/bin/socat stdin unix-listen:/tmp/exabgp;
11 | receive-routes;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/fetch_ripe_managed.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | # Job Snijders
4 |
5 | from aggregate6 import aggregate
6 |
7 | import ipaddress
8 | import requests
9 | import sys
10 |
11 | ripe_url = "http://ftp.ripe.net/ripe/stats/delegated-ripencc-latest"
12 |
13 | r = requests.get(ripe_url)
14 |
15 | pfx_list = []
16 |
17 | for entry in str(r.text).split('\n'):
18 | if not entry:
19 | continue
20 | try:
21 | afi, start_ip, count = entry.split('|')[2:5]
22 | except ValueError as e:
23 | print(entry)
24 | sys.exit(1)
25 | ip_type = entry.split('|')[-1]
26 | if not ip_type in ["allocated", "assigned"]:
27 | continue
28 | if afi == "ipv4":
29 | first_ip = ipaddress.ip_address(start_ip)
30 | last = int(first_ip) + int(count) - 1
31 | last_ip = ipaddress.ip_address(last)
32 | cidrs = ipaddress.summarize_address_range(first_ip, last_ip)
33 | for prefix in cidrs:
34 | pfx_list.append(str(prefix))
35 | if afi == "ipv6":
36 | pfx_list.append(("{}/{}".format(start_ip, count)))
37 |
38 | for prefix in aggregate(pfx_list):
39 | print(prefix)
40 |
--------------------------------------------------------------------------------
/irrexplorer/__init__.py:
--------------------------------------------------------------------------------
1 | __version__ = "0.0.5"
2 | __author__ = "Job Snijders, Peter van Dijk"
3 | __author_email__ = "job@instituut.net"
4 | __copyright__ = "Copyright 2015, Job Snijders & Peter van Dijk"
5 | __license__ = "BSD 2-Clause"
6 | __status__ = "Development"
7 | __url__ = "https://github.com/job/irrexplorer"
8 |
9 |
--------------------------------------------------------------------------------
/irrexplorer/bgpupdate.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Functionality to update BGP entries in IRRExplorer database.
5 | """
6 |
7 | import urllib2
8 | import ipaddr
9 | import logging
10 |
11 | INSERT_STM = "SELECT create_route (%s, %s, 'bgp');"
12 | DELETE_STM = "DELETE FROM routes USING sources WHERE routes.route = %s AND routes.asn = %s AND routes.source_id = sources.id AND sources.name = 'bgp';"
13 |
14 |
15 | def updateBGP(source_url, db):
16 |
17 | logging.info('Updating BGP information')
18 |
19 | source_routes = set()
20 |
21 | # get the bgp routes
22 | for line in urllib2.urlopen(source_url):
23 | route, asn = line.strip().split(' ')
24 | source_routes.add( (route, int(asn)) )
25 |
26 | fltrd_source_routes = set()
27 | for route, asn in source_routes:
28 | try:
29 | route_obj = ipaddr.IPNetwork(route)
30 | except ValueError:
31 | logging.error('Invalid route in BGP feed: %s' % route)
32 | continue
33 |
34 | # block router2router linknets / small blocks
35 | if route_obj.version == 4 and route_obj.prefixlen >= 29:
36 | continue
37 | if route_obj.version == 6 and route_obj.prefixlen >= 124:
38 | continue
39 |
40 | fltrd_source_routes.add((route, int(asn)))
41 |
42 | logging.info('BGP table fetched and table build, %i routes' % (len(source_routes)))
43 |
44 | # then the database routes
45 | db_routes = set()
46 | bgp_rows = db.query_source('bgp')
47 | logging.info('Got database entries, %i routes' % len(bgp_rows))
48 |
49 | for route, asn in bgp_rows:
50 | db_routes.add((route, int(asn)))
51 |
52 | # calculate the diff, intersection is just for logging
53 | routes_is = fltrd_source_routes & db_routes
54 | deprecated_routes = db_routes - fltrd_source_routes
55 | new_routes = fltrd_source_routes - db_routes
56 |
57 | logging.info('Routes: %i unchanged / %i deprecated / %i new' % (len(routes_is), len(deprecated_routes), len(new_routes)))
58 |
59 | # create + send update statements
60 | cur = db._get_cursor()
61 |
62 | for route, asn in deprecated_routes:
63 | cur.execute(DELETE_STM, (route, asn) )
64 |
65 | for route, asn in new_routes:
66 | cur.execute(INSERT_STM, (route, asn) )
67 |
68 | db.conn.commit()
69 | cur.close() # so it doesn't linger while sleeping
70 |
71 | logging.info('BPG update commit done and cursor closed')
72 |
73 |
74 |
--------------------------------------------------------------------------------
/irrexplorer/irrparser.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2015 Job Snijders
2 | # Copyright (C) 2015 NORDUnet A/S
3 | #
4 | # This file is part of IRR Explorer
5 | #
6 | # Redistribution and use in source and binary forms, with or without
7 | # modification, are permitted provided that the following conditions are met:
8 | #
9 | # 1. Redistributions of source code must retain the above copyright notice,
10 | # this list of conditions and the following disclaimer.
11 | #
12 | # 2. Redistributions in binary form must reproduce the above copyright notice,
13 | # this list of conditions and the following disclaimer in the documentation
14 | # and/or other materials provided with the distribution.
15 | #
16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | # ARISING IN ANY WAY OUT OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 | # POSSIBILITY OF SUCH DAMAGE.
27 |
28 |
29 |
30 | AS_SET = 'as-set'
31 | ROUTE = 'route'
32 |
33 |
34 | def readAttr(line):
35 | sp = line.split(':',1)[1]
36 | if '#' in sp:
37 | sp = sp.split('#',1)[0]
38 | return sp.strip()
39 |
40 |
41 | def convertASDot(origin):
42 | if '.' in origin:
43 | high, low = map(int, origin.split('.'))
44 | origin = (high << 16) + low
45 | return origin
46 |
47 |
48 | def irrParser(datasource):
49 |
50 | obj_type = None
51 | object_ = None
52 | origin = None
53 | source = None
54 | members = []
55 |
56 | for line in datasource:
57 |
58 | if line.startswith('route:') or line.startswith('route6:'):
59 | object_ = readAttr(line)
60 | obj_type = ROUTE
61 | ctx = None
62 |
63 | elif line.startswith('as-set:'):
64 | object_ = readAttr(line).upper()
65 | obj_type = AS_SET
66 | ctx = None
67 |
68 | elif line.startswith('origin:'):
69 | origin = readAttr(line)[2:]
70 | origin = convertASDot(origin)
71 | origin = int(origin)
72 | ctx = None
73 |
74 | elif line.startswith('source:'):
75 | source = readAttr(line).lower()
76 | ctx = None
77 |
78 | elif line.startswith('members:'):
79 | members += [ m.strip() for m in readAttr(line).split(',') if m.strip() ]
80 | ctx = members
81 |
82 | elif line.startswith((' ','\t')) and ctx:
83 | ctx += [ m.strip() for m in line.split(',') if m.strip() ]
84 |
85 | else:
86 | ctx = None
87 |
88 | if obj_type == AS_SET:
89 | return AS_SET, (object_, members, source)
90 | elif obj_type == ROUTE:
91 | return ROUTE, (object_, origin, source)
92 | else: # in case no route{,6} or as-set was found
93 | return None, None
94 |
--------------------------------------------------------------------------------
/irrexplorer/irrtest.data:
--------------------------------------------------------------------------------
1 | route: 207.72.0.0/14
2 | descr: MERIT Network Inc.
3 | 1000 Oakbrook Drive, Suite 200
4 | Ann Arbor
5 | MI 48104, USA
6 | origin: AS237
7 | mnt-by: MAINT-AS237
8 | changed: rik@merit.edu 20050922
9 | source: RADB
10 |
11 | as-set: AS-test1
12 | descr: Stub ASs for ClubNET
13 | members: AS5726, AS5736, AS20318
14 | admin-c: DG251
15 | tech-c: PC41
16 | notify: route@ns.clubnet.net
17 | mnt-by: MAINT-AS5736-ALTDB
18 | changed: pete@altadena.net 20010713
19 | source: ALTDB
20 |
21 | person: Job Snijders
22 | address: Theodorus Majofskistraat 100
23 | address: 1065 SZ Amsterdam
24 | address: The Netherlands
25 | remarks: PGP key is PGPKEY-7E5BEC10
26 | phone: +31-6-54942365
27 | nic-hdl: JWJS1-RIPE
28 | mnt-by: SNIJDERS-MNT
29 | source: RIPE # Filtered
30 |
31 | as-set: AS-test2
32 | descr: Stub ASs for ClubNET
33 | members: AS5726
34 | members: AS5736, AS20318
35 | admin-c: DG251
36 | tech-c: PC41
37 | notify: route@ns.clubnet.net
38 | mnt-by: MAINT-AS5736-ALTDB
39 | changed: pete@altadena.net 20010713
40 | source: ALTDB
41 |
42 | as-set: AS-test3
43 | descr: Stub ASs for ClubNET
44 | members: AS5726
45 | members: AS5736, AS20318 # herpa
46 | admin-c: DG251
47 | tech-c: PC41
48 | notify: route@ns.clubnet.net
49 | mnt-by: MAINT-AS5736-ALTDB
50 | changed: pete@altadena.net 20010713
51 | source: ALTDB
52 |
53 | as-set: AS-PACIFIC-INTERNET-IX
54 | descr: Pacific Internet Malaysia
55 | c/o 89 Science Park Drive
56 | #02-05/06 Rutherford
57 | Singapore 118261
58 | Republic of Singapore
59 | Tel: +65-6872-1010
60 | Fax: +65-6872-1011
61 | members: AS4628, AS4629
62 | remarks: Peering with AS4628 and AS4629
63 | Email abuse@pacific.net.sg for security issues
64 | Email noc@pacific.net.sg for network issues
65 | admin-c: WH1-AP
66 | tech-c: WH1-AP
67 | notify: noc@pacific.net.sg
68 | mnt-by: MAINT-AS9904
69 | changed: hoou@pacific.net.sg 20020328
70 | source: ALTDB
71 |
72 | as-set: AS-NIXC
73 | descr: ASNs announced by NIXC.
74 | members: AS-NIXC-BACKBONE, AS-NIXC-CUSTOMERS
75 | admin-c: Darrin Walton
76 | tech-c: Darrin Walton
77 | notify: radb@nixc.net
78 | mnt-by: MAINT-NIXC
79 | changed: darrinw@nixc.net 20020801
80 | source: ALTDB
81 |
82 | as-set: AS5042:AS-PEERS
83 | descr: IWT Peers
84 | members: AS3638, AS8001, AS5430, AS9156, AS13768, AS10588
85 | admin-c: LNK
86 | tech-c: LNK
87 | notify: noc@informationwave.net
88 | mnt-by: MAINT-AS5042
89 | changed: missnglnk@informationwave.net 20021013
90 | source: ALTDB
91 |
92 | as-set: AS-CABOTELECOM-CUST-IPv6
93 | descr: Customers from Cabo Telecom.
94 | members: AS28339 # ACT
95 | members: AS262857 # UFRN
96 | members: AS262876 # UNP
97 | tech-c: ARCTE-LACNIC
98 | admin-c: ARCTE-LACNIC
99 | notify: noc@cabotelecom.com.br
100 | mnt-by: CABONATAL-BR
101 | changed: eduardo.andrez@cabotelecom.com.br 20110403
102 | source: ALTDB
103 |
104 | as-set: AS-NLAYER-CUSTOMERS
105 | descr: nLayer Communications - Customer AS-SET
106 | members: AS10625, AS10692, AS10905, AS10940, AS11013, AS11280, AS11282,
107 | AS11346, AS11478, AS11483, AS11682, AS11696, AS11763, AS11931,
108 | AS-1215, AS12284, AS13335, AS1341, AS13557, AS13722, AS13730,
109 | AS13803, AS1403, AS14061, AS14193, AS14200, AS1421, AS14288,
110 | AS1442, AS14601, AS14627, AS14670, AS14829, AS14929, AS14987,
111 | AS15024, AS15072, AS15149, AS15266, AS15695, AS16162, AS16626,
112 | AS16632, AS16647, AS16839, AS16986, AS17139, AS17246, AS18549,
113 | AS18608, AS18787, AS18793, AS18978, AS18981, AS19066, AS19222,
114 | AS19230, AS19245, AS19551, AS197669, AS197853, AS199636, AS19970,
115 | AS199799, AS20144, AS20223, AS21267, AS21321, AS21534, AS21797,
116 | AS21840, AS22300, AS22518, AS22543, AS22653, AS22915, AS23136,
117 | AS23367, AS23421, AS23498, AS23522, AS23533, AS236, AS24894,
118 | AS25151, AS25605, AS25764, AS25780, AS25782, AS25844, AS26288,
119 | AS26342, AS26424, AS26449, AS26484, AS26548, AS26642, AS26697,
120 | AS26938, AS26967, AS26972, AS27280, AS27381, AS27413,
121 | AS-27506-TRANSIT, AS27908, AS28786, AS29706, AS29846, AS29909,
122 | AS30058, AS30238, AS30373, AS30502, AS-30517-ASSOCIATED, AS31402,
123 | AS32063, AS32131, AS32286, AS32313, AS32392,
124 | AS32421:AS-CUSTOMERS, AS32489, AS32632, AS32780, AS32782,
125 | AS32977, AS33065, AS33314, AS33404, AS34967, AS35180, AS3584,
126 | AS35890, AS35906, AS3595, AS35975, AS36137, AS36323, AS36605,
127 | AS36614, AS3737, AS376:AS-CUSTOMERS, AS3842, AS38880, AS393241,
128 | AS3943, AS39995, AS40041, AS40125, AS40217, AS40335, AS40353,
129 | AS40418, AS40428, AS40539, AS40676, AS40784, AS40926, AS42369,
130 | AS43639, AS43664, AS44965, AS4544:AS-NA-CUSTOMERS, AS45474,
131 | AS46261, AS46351, AS46489, AS46609, AS46652, AS46665, AS46844,
132 | AS46922, AS47484, AS4866, AS50468, AS51205, AS53265, AS53301,
133 | AS53342, AS53428, AS53429, AS53582, AS53817, AS53969, AS54113,
134 | AS54136, AS54235, AS54288, AS54329, AS54333, AS54335, AS54460,
135 | AS54491, AS54527:AS-GLOBAL, AS54540, AS54594, AS54600, AS54778,
136 | AS54829, AS54905, AS54953, AS54957, AS54963, AS54994, AS55011,
137 | AS55041, AS55069, AS5645:AS-CUSTOMERS, AS-5713, AS57624, AS5784,
138 | AS60736, AS61373, AS62195, AS62567, AS62713, AS62725, AS62870,
139 | AS62982, AS63003, AS63008, AS63058, AS6643, AS7219, AS7456,
140 | AS792, AS-ACEDATACENTERS, AS-ACN, AS-ADTAQ, AS-AFILIAS-FULLMONTY,
141 | AS-AFNCA, AS-AKAMAI, AS-APPLIEDOPS, AS-AREN, AS-ARIALINK,
142 | AS-AVESTANETWORKS, AS-BIGWELLS, AS-BLIP, AS-BTS, AS-BURSTNET,
143 | AS-BXI, AS-C1, AS-C3, AS-CACHENETWORKS, AS-CBISP, AS-CHOOPA,
144 | AS-CIFNET, AS-CLUETRUST, AS-CNSERVERS, AS-COGNET, AS-COLOAT,
145 | AS-COLOCROSSING, AS-CORESITE-SET, AS-CQ-GIGENET, AS-CYBERVERSE,
146 | AS-DACENTEC, AS-DCC, AS-DEAC, AS-DISTRIBUTEL, AS-DVLABS,
147 | AS-ED-ASH, AS-EDGECAST, AS-ENA, AS-ENERGYGROUPNETWORKS,
148 | AS-FIBERINTERNETCENTER, AS-FORTRESS, AS-FOXVALLEY,
149 | AS-GIGANEWS-ALL, AS-GORACK, AS-GREATACCESS, AS-GTCOMM1,
150 | AS-HAPNET, AS-HGC, AS-HOSTVIRTUAL, AS-ICANNDNSW, AS-IDCGLOBAL,
151 | AS-INFORELAY, AS-INFOSTEWARDS, AS-INMOTION, AS-INTERACTIVE3D,
152 | AS-VIO, AS-VOBIZ, AS-VOXEL, AS-VPLS, AS-WBTSGBR, AS-WEBAIR,
153 | AS-WEBNX, AS-WEBPASS, AS-WESTHOST, AS-WHS-US, AS-XMISSION,
154 | AS-XPLUSONE, AS-YELLOWFIBER, AS-YOUR-GLOBAL-SET
155 | admin-c: NIA1-ARIN
156 | tech-c: NLAYE-ARIN
157 | mnt-by: MAINT-NLAYER
158 | changed: ipeng@nlayer.net 20150208
159 | source: ALTDB
160 |
161 | as-set: AS-NLAYER-CUSTOMERS2
162 | descr: nLayer Communications - Customer AS-SET
163 | members: AS10625, AS10692, AS10905, AS10940, AS11013, AS11280, AS11282,
164 | AS11346, AS11478, AS11483, AS11682, AS11696, AS11763, AS11931,
165 | AS-1215, AS12284, AS13335, AS1341, AS13557, AS13722, AS13730,
166 | AS-BXI, AS-C1, AS-C3, AS-CACHENETWORKS, AS-CBISP, AS-CHOOPA,
167 | AS-CIFNET, AS-CLUETRUST, AS-CNSERVERS, AS-COGNET, AS-COLOAT,
168 | AS-COLOCROSSING, AS-CORESITE-SET, AS-CQ-GIGENET, AS-CYBERVERSE, # herpa
169 | AS-XPLUSONE, AS-YELLOWFIBER, AS-YOUR-GLOBAL-SET #derpa
170 | admin-c: NIA1-ARIN
171 | tech-c: NLAYE-ARIN
172 | mnt-by: MAINT-NLAYER
173 | changed: ipeng@nlayer.net 20150208
174 | source: ALTDB
175 |
176 |
--------------------------------------------------------------------------------
/irrexplorer/irrupdate.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Functionality to update IRR entries in IRRExplorer database via NRTM streaming
5 | """
6 |
7 | import logging
8 |
9 | import ipaddr
10 |
11 | from irrexplorer import nrtm, irrparser
12 |
13 |
14 |
15 | CREATE_ROUTE = "SELECT create_route (%s, %s, %s);"
16 | CREATE_AS_SET = "SELECT create_as_set (%s, %s, %s);"
17 |
18 | DELETE_ROUTE = "DELETE FROM routes USING sources WHERE routes.route = %s AND routes.asn = %s AND routes.source_id = sources.id AND sources.name = %s;"
19 | DELETE_AS_SET = "DELETE FROM as_sets USING sources WHERE as_sets.as_macro = %s AND as_sets.source_id = sources.id AND sources.name = %s;"
20 |
21 | SELECT_SERIAL = "SELECT last_seen_serial FROM sources WHERE name = %s"
22 | UPDATE_SERIAL = "UPDATE sources SET last_seen_serial = %s WHERE sources.name = %s"
23 |
24 |
25 |
26 | class IRRUpdateError(Exception):
27 | pass
28 |
29 |
30 |
31 | def update_irr(host, port, source, db):
32 |
33 | source = source.lower() # we always lowercase this
34 |
35 | # get serial from database
36 | cur = db._get_cursor()
37 | cur.execute(SELECT_SERIAL, (source,))
38 | srow = cur.fetchall()
39 | cur.close()
40 |
41 | if not srow:
42 | raise IRRUpdateError('No serial for source %s found, cannot continue' % source)
43 |
44 | db_serial = srow[0][0]
45 | serial = int(db_serial) + 1 # don't do the one we last saw
46 |
47 | logging.info('Streaming from %s:%s/%s from serial %s' % (host, port, source, serial))
48 | c = nrtm.NRTMStreamer(host, source, serial, port)
49 |
50 | stms = []
51 |
52 | changes = {}
53 |
54 | for tag, serial, (obj_type, obj_data) in c.stream():
55 |
56 | if not obj_data:
57 | continue # skip over unsupported objects
58 |
59 | obj, data, obj_source = obj_data
60 | if obj and not obj_source == source:
61 | logging.info("Weird source difference, skipping: %s vs %s at %s in: %s, %s" % (obj_source, source, serial, obj, data))
62 | continue
63 |
64 | #print tag, serial, obj_type, obj, source
65 |
66 | if tag == 'ADD':
67 | if obj_type == irrparser.ROUTE:
68 | changes['add_route'] = changes.get('add_route', 0) + 1
69 | # test if this is a proper prefix
70 | try:
71 | ipaddr.IPNetwork(obj, strict=True)
72 | except ValueError:
73 | logging.error('Prefix %s from source %s, is not a proper prefix, skipping object')
74 | continue
75 |
76 | # Sometimes (and only sometimes) an ADD will be send for something already exists (I am looking at you altdb)
77 | # Previously we handled this by deleting the route first. After switching to PostgreSQL we use the upsert feature
78 | # in the create functions, so no need to handle it here.
79 | stms.append( ( CREATE_ROUTE, (obj, data, source) ) )
80 |
81 | elif obj_type == irrparser.AS_SET:
82 | changes['add_as_set'] = changes.get('add_as_set', 0) + 1
83 | # irrd doesn't seem to generate DEL before updates to as-sets
84 | # the create function will overwrite the set if it already exists
85 | stms.append( ( CREATE_AS_SET, (obj, data, source) ) )
86 | else:
87 | logging.warning('Weird add %s %s %s' % (tag, serial, obj_type))
88 |
89 | elif tag == 'DEL':
90 | if obj_type == irrparser.ROUTE:
91 | changes['del_route'] = changes.get('del_route', 0) + 1
92 | stms.append( ( DELETE_ROUTE, (obj, data, source) ) )
93 | elif obj_type == irrparser.AS_SET:
94 | changes['del_as_set'] = changes.get('del_as_set', 0) + 1
95 | # this one almost never happens, so it is tricky to test it
96 | stms.append( ( DELETE_AS_SET, (obj, source) ) )
97 | else:
98 | logging.warning('Weird del %s %s %s' % (tag, serial, obj_type))
99 |
100 | elif not tag:
101 | pass
102 |
103 | else:
104 | logging.warning('Weird tag: %s %s %s ' % tag, serial, obj_type)
105 |
106 | logging.warning('Changes: %s' % ' '.join( [ '%s: %s' % (k, v) for k,v in changes.items() ] ) )
107 | if stms:
108 | # only update serial, if we actually got something
109 | stms.append( ( UPDATE_SERIAL, (serial, source) ) )
110 |
111 | # debug
112 | logging.debug("--")
113 | logging.debug(" Will execute the following statements")
114 | for stm, arg in stms:
115 | logging.debug("%s / %s" % (stm, arg))
116 | logging.debug("--")
117 |
118 | if stms:
119 | # send delete/insert statements
120 | cur = db._get_cursor()
121 |
122 | for stm, arg in stms:
123 | #print stm, arg
124 | cur.execute(stm, arg)
125 |
126 | db.conn.commit()
127 | cur.close() # so it doesn't linger while sleeping
128 |
129 | logging.info('IRR update committed and cursor closed')
130 | else:
131 | logging.info('No updates for IRR source %s' % source)
132 |
--------------------------------------------------------------------------------
/irrexplorer/nrtm.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2015 Job Snijders
2 | # Copyright (C) 2015 NORDUnet A/S
3 | #
4 | # This file is part of IRR Explorer
5 | #
6 | # Redistribution and use in source and binary forms, with or without
7 | # modification, are permitted provided that the following conditions are met:
8 | #
9 | # 1. Redistributions of source code must retain the above copyright notice,
10 | # this list of conditions and the following disclaimer.
11 | #
12 | # 2. Redistributions in binary form must reproduce the above copyright notice,
13 | # this list of conditions and the following disclaimer in the documentation
14 | # and/or other materials provided with the distribution.
15 | #
16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | # ARISING IN ANY WAY OUT OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 | # POSSIBILITY OF SUCH DAMAGE.
27 |
28 | import socket
29 |
30 | from irrexplorer import irrparser
31 |
32 |
33 | DEFAULT_PORT = 43
34 |
35 |
36 | class NRTMError(Exception):
37 | pass
38 |
39 |
40 |
41 | class NRTMStreamer(object):
42 | """nrtm client class"""
43 | def __init__(self, host, source, start_serial, port=DEFAULT_PORT):
44 |
45 | self.host = host
46 | self.source = source
47 | self.serial = start_serial
48 | self.port = port
49 |
50 |
51 | def nrtm_connect(self):
52 |
53 | (family, socktype, proto, canonname, sockaddr) = socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM)[0]
54 | s = socket.socket(family, socktype, proto)
55 | s.connect(sockaddr)
56 | f = s.makefile()
57 | f.write('!!\n!nIRRExplorer\n')
58 | f.flush()
59 | #f.write('-k -g {}:3:{}-LAST\n'.format(self.source, self.serial))
60 | f.write('-g {}:3:{}-LAST\n'.format(self.source, self.serial))
61 | f.flush()
62 | return f
63 |
64 |
65 | def stream(self):
66 |
67 | data_source = self.nrtm_connect()
68 | #data_source = open('nrtm.dump')
69 |
70 | for line in data_source:
71 |
72 | if not line.strip():
73 | continue # blank line
74 |
75 | if line.startswith('%'):
76 | # print '>>', line,
77 | c_line = line[1:].strip()
78 | if c_line == '':
79 | continue # blank comment
80 |
81 | cl = c_line.lower()
82 |
83 | if cl.startswith('start'):
84 | print c_line
85 | elif cl.startswith(('error','warning')):
86 | raise NRTMError(c_line)
87 | elif cl.startswith('end'):
88 | raise StopIteration
89 | else:
90 | print 'Did not understand the following comment line:'
91 | print line,
92 | continue
93 |
94 | if line.startswith(('#', 'C')):
95 | continue
96 |
97 | if line.startswith(('ADD', 'DEL')):
98 | tag, serial = line.strip().split(' ')
99 | data_source.readline() # skip over first newline after ADD/DEL
100 |
101 | object_data = []
102 |
103 | while True:
104 | obj_line = data_source.readline()
105 | if not obj_line == '\n':
106 | object_data.append(obj_line)
107 | else:
108 | break
109 |
110 | obj = irrparser.irrParser(object_data)
111 | if obj:
112 | yield tag, int(serial), obj
113 | else:
114 | print "Unsupported: %s" % object_data[0]
115 | yield None, int(serial), (None, (None, None, None))
116 |
117 | else:
118 | print 'Did not understand the following line:'
119 | print line,
120 |
121 |
122 | # Streaming and data source needs better seperation for testing
123 |
124 | # if __name__ == '__main__':
125 | # f = open('nrtm.dump')
126 | # for tag, serial, (obj_type, obj_data) in nrtmParser(f):
127 | # obj, data, source = obj_data
128 | # print tag, serial, obj_type, obj, source
129 |
130 |
--------------------------------------------------------------------------------
/irrexplorer/report.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # Copyright (c) 2015, Job Snijders
3 | # Copyright (c) 2015, NORDUnet A/S
4 | #
5 | # This file is part of IRR Explorer
6 | #
7 | # Redistribution and use in source and binary forms, with or without
8 | # modification, are permitted provided that the following conditions are met:
9 | #
10 | # 1. Redistributions of source code must retain the above copyright notice,
11 | # this list of conditions and the following disclaimer.
12 | #
13 | # 2. Redistributions in binary form must reproduce the above copyright notice,
14 | # this list of conditions and the following disclaimer in the documentation
15 | # and/or other materials provided with the distribution.
16 | #
17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 | # POSSIBILITY OF SUCH DAMAGE.
28 |
29 | import time
30 |
31 |
32 | SOURCE = 'source'
33 | RIPE = 'ripe'
34 | BGP = 'bgp'
35 |
36 | # IRR_DBS = ['afrinic', 'altdb', 'apnic', 'arin', 'bboi', 'bell', 'gt', 'jpirr', 'level3', 'nttcom', 'radb', 'rgnet', 'savvis', 'tc', 'ripe']
37 |
38 |
39 | class NoPrefixError(Exception):
40 | pass
41 |
42 |
43 |
44 | def add_prefix_advice(prefixes):
45 |
46 | # default, primary, succes, info, warning, danger
47 | for pfx, pfx_data in prefixes.items():
48 | print 'Prefix: %s, data: %s' % (pfx, pfx_data)
49 | pfx_source = pfx_data[SOURCE]
50 |
51 | anywhere = set()
52 | for entries in pfx_source.values():
53 | for entry in entries:
54 | anywhere.add(entry)
55 | anywhere = list(anywhere)
56 |
57 | anywhere_not_ripe = set()
58 | for db, entries in pfx_source.items():
59 | if db != RIPE:
60 | for entry in entries:
61 | anywhere_not_ripe.add(entry)
62 | anywhere_not_ripe = list(anywhere_not_ripe)
63 |
64 | #print ' IRR orgins:', anywhere
65 | #print ' IRR orgins % ripe:', anywhere_not_ripe
66 |
67 | if not BGP in pfx_data:
68 | bgp_origin = None
69 | else:
70 | # afaict this should never happen, at least not as long as we only have a single table
71 | if len(pfx_data[BGP]) > 2:
72 | print 'Multiple BGP sources:', pfx_data[BGP], 'only using first origin'
73 | bgp_origin = list(pfx_data[BGP])[0]
74 |
75 | # check if this is rfc managed space
76 | managed = False
77 |
78 | for source in pfx_data:
79 | if source.endswith('_managed') and source.lower() != 'ripe_managed':
80 | rfc_source = source.rsplit('_',1)[0]
81 | pfx_data['advice'] = "Prefix is %s space. Drunk engineer." % rfc_source
82 | pfx_data['label'] = "warning"
83 | managed = True
84 | break
85 |
86 | if managed:
87 | continue # don't bother checking anything else
88 |
89 | if 'ripe_managed' in pfx_data:
90 |
91 | if 'ripe' in pfx_source:
92 |
93 | if bgp_origin and bgp_origin in pfx_source['ripe']:
94 |
95 | if len(anywhere) == 1: # only ripe as origin
96 | pfx_data['advice'] = "Perfect"
97 | pfx_data['label'] = "success"
98 |
99 | elif [bgp_origin] == anywhere:
100 | pfx_data['advice'] = "Proper RIPE DB object, but foreign objects also exist, consider remoing these."
101 | pfx_data['label'] = "warning"
102 |
103 | elif anywhere_not_ripe:
104 | pfx_data['advice'] = "Proper RIPE DB object, but foreign objects also exist, consider removing these. BGP origin does not match all IRR entries."
105 | pfx_data['label'] = "danger"
106 |
107 | elif len(anywhere) > 1:
108 | pfx_data['advice'] = "Multiple entries exists in RIPE DB, with different origin. Consider removing conflicting entries."
109 | pfx_data['label'] = "warning"
110 |
111 | else:
112 | pfx_data['advice'] = "Looks good, but multiple entries exists in RIPE DB"
113 | pfx_data['label'] = "success"
114 |
115 | elif bgp_origin and pfx_source:
116 | pfx_data['advice'] = "Prefix is in DFZ, but registered with wrong origin in RIPE!"
117 | pfx_data['label'] = "danger"
118 |
119 | else: # no bgp origin
120 | # same as last else clause, not sure if this could be made a bit better
121 | if ':' in pfx:
122 | pfx_data['advice'] = "Look like network is not announcing registered v6 prefix yet"
123 | else:
124 | pfx_data['advice'] = "Not seen in BGP, but (legacy?) route-objects exist, consider clean-up"
125 | pfx_data['label'] = "info"
126 |
127 | else: # no ripe registration
128 |
129 | if bgp_origin:
130 | # do if on as match
131 | if anywhere: # could use anywhere_but_ripe - result would be the same
132 | if [bgp_origin] == anywhere:
133 | pfx_data['advice'] = "Prefix is in DFZ and has an IRR record, but NOT in RIPE! BGP origin matches IRR entries."
134 | pfx_data['label'] = "warning"
135 | else:
136 | pfx_data['advice'] = "Prefix is in DFZ and has an IRR record, but NOT in RIPE! BGP origin does not match all IRR entries."
137 | pfx_data['label'] = "danger"
138 | else:
139 | pfx_data['advice'] = "Prefix is in DFZ, but NOT registered in any IRR and should go into RIPE!"
140 | pfx_data['label'] = "danger"
141 |
142 | else:
143 | pfx_data['advice'] = "Route objects in foreign registries exist, but no BGP origin. Consider moving IRR object to RIPE DB or deleting them."
144 | pfx_data['label'] = "warning"
145 |
146 | elif bgp_origin: # not ripe managed, but have bgp_origin
147 |
148 | if bgp_origin in anywhere:
149 |
150 | if len(anywhere) == 1:
151 | pfx_data['advice'] = "Looks good: BGP origin consistent with AS in route-objects"
152 | pfx_data['label'] = "success"
153 | else:
154 | pfx_data['advice'] = "Multiple route-object exist with different origins"
155 | pfx_data['label'] = 'warning'
156 |
157 | else:
158 | pfx_data['advice'] = "Prefix in DFZ, but no route-object with correct origin anywhere"
159 | pfx_data['label'] = "danger"
160 |
161 | else: # not ripe managed, no bgp origin
162 | if ':' in pfx:
163 | pfx_data['advice'] = "Look like network is not announcing registered v6 prefix yet"
164 | else:
165 | pfx_data['advice'] = "Not seen in BGP, but (legacy?) route-objects exist, consider clean-up"
166 | pfx_data['label'] = "info"
167 |
168 |
169 | return prefixes
170 |
171 |
172 |
173 | def prefix(pgdb, prefix):
174 | """
175 | - find least specific
176 | - search in BGP for more specifics
177 | - search in IRR for more specifics
178 | - check all prefixes whether they are RIPE managed or not
179 | - return dict
180 | """
181 |
182 | t_start = time.time()
183 |
184 | print 'Prefix report: %s' % (prefix,)
185 |
186 | routes = pgdb.query_prefix(prefix)
187 |
188 | prefixes = _build_prefix_dict(routes)
189 |
190 | # avoid spamming log too much
191 | if len(prefixes) < 20:
192 | print 'Prefixes:', prefixes.keys()
193 | else:
194 | print 'Prefixes: <%i>' % len(prefixes)
195 |
196 | # TODO if we find any prefixes larger than the inputted one, we should find prefixes covered by that prefixes
197 | # Go through the prefixes, find the shortest one, if it is different from the inputted one, do another search
198 |
199 | add_prefix_advice(prefixes)
200 |
201 | print 'Advice:'
202 | for p,d in prefixes.items():
203 | print '%s: %s' % (p,d['advice'])
204 |
205 | # Move source out into top dict, to fit with the datatables stuff
206 | for pfx_data in prefixes.values():
207 | pfx_data.update(pfx_data.pop(SOURCE))
208 |
209 | t_delta = time.time() - t_start
210 | print 'Time for prefix report for %s: %s\n' % (prefix, round(t_delta,2))
211 |
212 | return prefixes
213 |
214 |
215 |
216 | def _build_prefix_dict(db_result):
217 |
218 | result = {}
219 |
220 | for route, asn, source, managed in db_result:
221 | #print 'BDP', route, asn, source, managed
222 | ps = result.setdefault(route, {}).setdefault(SOURCE, {})
223 | if not asn in ps.get(source, []): # we can get duplicates due to htj's sql limitations
224 | ps.setdefault(source, []).append(asn)
225 | if managed:
226 | result[route][managed] = True
227 |
228 | # move bgp out from sources and into top-level dict for the prefix
229 | for data in result.values():
230 | if BGP in data[SOURCE]:
231 | data[BGP] = data[SOURCE].pop(BGP)
232 |
233 | return result
234 |
235 |
236 |
237 | def as_prefixes(pgdb, as_number):
238 |
239 | if not type(as_number) is int:
240 | raise ValueError('Invalid argument provided for as number')
241 |
242 | print 'AS Prefix Report: ', as_number
243 |
244 | t_start = time.time()
245 |
246 | prefixes = pgdb.query_as(as_number)
247 |
248 | # do deep as query if prefix set is sufficiently small to do it fast
249 | # we could probably go to ~1000 here
250 | if len(prefixes) < 1000:
251 | print 'Performing deep query for AS', as_number
252 | prefixes = pgdb.query_as_deep(as_number)
253 |
254 | result = _build_prefix_dict(prefixes)
255 |
256 | add_prefix_advice(result)
257 |
258 | print 'Advice:'
259 | for p,d in result.items():
260 | print '%s: %s' % (p,d['advice'])
261 |
262 | # OK, this is not how i want to do things, but I cannot figure out the javascript stuff
263 | for pfx_data in result.values():
264 | pfx_data.update(pfx_data.pop(SOURCE))
265 |
266 | t_delta = time.time() - t_start
267 | print 'Time for AS prefixes for %s: %s' % (as_number, round(t_delta,2))
268 | print
269 |
270 | return result
271 |
272 |
273 |
274 | def macro_expand(pgdb, as_macro):
275 |
276 | print 'Macro Expand Report:', as_macro
277 |
278 | t_start = time.time()
279 |
280 | macros = pgdb.query_as_macro_expand(as_macro)
281 |
282 | result = []
283 | for macro, source, depth, path, members in macros:
284 | e = { 'as_macro' : macro,
285 | 'source' : source,
286 | 'depth' : depth,
287 | 'path' : path,
288 | 'members' : members
289 | }
290 | result.append(e)
291 |
292 | t_delta = time.time() - t_start
293 | print 'Time for macro expand report for %s: %s' % (as_macro, round(t_delta,2))
294 | print
295 |
296 | return result
297 |
298 |
299 |
300 | def macro_contain(pgdb, as_object):
301 |
302 | print 'Macro Contains Report:', as_object
303 |
304 | t_start = time.time()
305 |
306 | macros = pgdb.query_as_contain(as_object)
307 |
308 | result = {}
309 | for macro, source in macros:
310 | result.setdefault(macro, {})[source] = True
311 |
312 | t_delta = time.time() - t_start
313 |
314 | print 'Time for as contains report for %s: %s' % (as_object, round(t_delta,2))
315 | print
316 |
317 | return result
318 |
319 |
--------------------------------------------------------------------------------
/irrexplorer/sqldb.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2015, NORDUnet A/S
2 | #
3 | # This file is part of IRR Explorer
4 | #
5 | # Redistribution and use in source and binary forms, with or without
6 | # modification, are permitted provided that the following conditions are met:
7 | #
8 | # 1. Redistributions of source code must retain the above copyright notice,
9 | # this list of conditions and the following disclaimer.
10 | #
11 | # 2. Redistributions in binary form must reproduce the above copyright notice,
12 | # this list of conditions and the following disclaimer in the documentation
13 | # and/or other materials provided with the distribution.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 | # POSSIBILITY OF SUCH DAMAGE.
26 |
27 | """
28 | This module provides a small abstraction over the sql database.
29 | """
30 |
31 | import psycopg2
32 |
33 |
34 |
35 | class IRRSQLDatabase:
36 |
37 | def __init__(self, dsn):
38 |
39 | self.dsn = dsn
40 | self.conn = None
41 |
42 |
43 | def _get_cursor(self):
44 |
45 | if self.conn is None:
46 | self.conn = psycopg2.connect("dbname=irrexplorer user=irrexplorer")
47 | return self.conn.cursor()
48 |
49 |
50 | def _execute_fetchall(self, query, args):
51 |
52 | cur = self._get_cursor()
53 | cur.execute(query, args)
54 | rows = cur.fetchall()
55 | return rows
56 |
57 |
58 | def query_prefix(self, prefix):
59 |
60 | query = """SELECT rv.route, rv.asn, rv.source, mrv.source||'_managed' AS managed
61 | FROM routes_view rv
62 | JOIN routes_view r ON cidr_to_range(rv.route) && cidr_to_range(r.route)
63 | LEFT OUTER JOIN managed_routes_view mrv ON rv.route && mrv.route
64 | WHERE r.route && %s;"""
65 |
66 | return self._execute_fetchall(query, (prefix,))
67 |
68 |
69 | def query_source(self, source):
70 | """
71 | source --> [ (route, asn) ]
72 | """
73 | query = "SELECT route, asn FROM routes_view WHERE source = %s;"
74 | return self._execute_fetchall(query, (source,))
75 |
76 |
77 | def query_as(self, asn):
78 |
79 | query = """SELECT rv.route, rv.asn, rv.source, mrv.source||'_managed' as managed_routes
80 | FROM routes_view rv
81 | LEFT OUTER JOIN managed_routes_view mrv ON (rv.route && mrv.route)
82 | WHERE rv.asn = %s;"""
83 | return self._execute_fetchall(query, (asn,))
84 |
85 |
86 | def query_as_deep(self, asn):
87 |
88 | # This query find all prefixes that are registered/homing from and AS number AND
89 | # any other prefixes that covers/are covered by any of those prefixes
90 | # Furthermore, managed prefixes and source are added for matching prefixes.
91 | # These have an entry in the fouth column. Note that duplicates can be created here (but managed space should not overlap)
92 | # The adresss range of 2002::/16 and 192.88.99.0/24 are 6t40 addresses with lots of entries, and hence filtered out
93 |
94 | query = """
95 | SELECT DISTINCT rv.route, rv.asn, rv.source, mrv.source||'_managed' as managed_routes
96 | FROM
97 | (SELECT DISTINCT route FROM routes_view WHERE asn = %s) r
98 | JOIN routes_view rv ON cidr_to_range(r.route) && cidr_to_range(rv.route) AND NOT rv.route <<= '2002::/16'::cidr AND NOT rv.route <<= '192.88.99.0/24'::cidr
99 | LEFT OUTER JOIN managed_routes_view mrv ON (rv.route && mrv.route);
100 | """
101 |
102 | return self._execute_fetchall(query, (asn,))
103 |
104 |
105 | def query_as_contain(self, as_):
106 |
107 | query = "SELECT as_macro, source FROM as_sets_view WHERE %s = any(members);"
108 | return self._execute_fetchall(query, (as_,))
109 |
110 |
111 | def query_as_macro(self, as_macro):
112 |
113 | query = """SELECT members, source FROM as_sets_view WHERE as_macro = %s;"""
114 | return self._execute_fetchall(query, (as_macro,))
115 |
116 |
117 | def query_as_macro_expand(self, as_macro):
118 |
119 | # Recusive sql query, hang on to your shorts
120 | # Some as macro seem to either take a long time, or somehow loop forever, so added limit
121 | # The reason for this is not due to cycles as such, but because the query expands every as-macro path
122 | # This means that the same as macro will be listed multiple times. this means that queries can take a
123 | # very long. In particular, if there are multiple paths to a big macro, the whole thing will blow up.
124 |
125 | query = """WITH RECURSIVE member_list(as_macro, path, members, source, depth, cycle) AS (
126 | SELECT as_macro, ARRAY[as_macro], members, source, 1 AS depth, false FROM as_sets_view WHERE as_macro ILIKE %s
127 | UNION
128 | SELECT a.as_macro, path || a.as_macro, a.members, a.source, depth+1 AS depth, a.as_macro = ANY(path) AS cycle FROM as_sets_view a
129 | JOIN member_list b ON ( a.as_macro = ANY(b.members) AND NOT cycle)
130 | )
131 | SELECT as_macro, source, depth, path, members FROM member_list LIMIT 10000;
132 | """
133 | return self._execute_fetchall(query, (as_macro,))
134 |
135 |
136 |
137 | if __name__ == '__main__':
138 |
139 | dsn = "dbname=irrexplorer"
140 | db = IRRSQLDatabase(dsn)
141 |
142 | print 'Prefix'
143 | r1 = db.query_prefix('109.105.113.0/24')
144 | print r1
145 |
146 | print
147 | print 'AS Prefixes'
148 | r4 = db.query_as(2603)
149 | for r,a,s,m in r4:
150 | print r,a,s,m
151 |
152 | print
153 | print 'AS contain'
154 | r5 = db.query_as_contain('AS-SUNET')
155 | for m,s in r5:
156 | print m,s
157 |
158 | print
159 | print 'AS macro members'
160 | r6 = db.query_as_macro('AS-IS')
161 | for m,s in r6:
162 | print s,m
163 |
164 | print
165 | print 'AS macro expand'
166 | r7 = db.query_as_contain('AS-IS')
167 | for m,s in r7:
168 | print s,m
169 |
170 |
--------------------------------------------------------------------------------
/irrexplorer/utils.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2015, Job Snijders
2 | # Copyright (c) 2015, NORDUnet A/S
3 | #
4 | # This file is part of IRR Explorer
5 | #
6 | # Redistribution and use in source and binary forms, with or without
7 | # modification, are permitted provided that the following conditions are met:
8 | #
9 | # 1. Redistributions of source code must retain the above copyright notice,
10 | # this list of conditions and the following disclaimer.
11 | #
12 | # 2. Redistributions in binary form must reproduce the above copyright notice,
13 | # this list of conditions and the following disclaimer in the documentation
14 | # and/or other materials provided with the distribution.
15 | #
16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 | # POSSIBILITY OF SUCH DAMAGE.
27 |
28 | """
29 | Utility stuff.
30 |
31 | Right now it just classifies search strings as the right object.
32 | """
33 |
34 | import ipaddr
35 |
36 |
37 | class SearchObject(object):
38 |
39 | def __init__(self, value):
40 | self.value = value
41 |
42 |
43 | class Prefix(SearchObject): pass # also used for ip addresses
44 | class ASNumber(SearchObject): pass
45 | class ASMacro(SearchObject): pass
46 |
47 |
48 |
49 | def classifySearchString(data):
50 |
51 | data = data.strip()
52 |
53 | asn = None
54 | try:
55 | asn = int(data)
56 | except ValueError:
57 | pass
58 | if asn:
59 | if asn < 1:
60 | raise ValueError('Invalid as number (negative or zero)')
61 | return ASNumber(asn)
62 |
63 | if data.upper().startswith('AS-'):
64 | return ASMacro(data.upper()) # as macros are always uppcase
65 |
66 | if data.upper().startswith('AS'):
67 | try:
68 | return ASNumber(int(data[2:]))
69 | except ValueError:
70 | return ASMacro(data)
71 |
72 | try:
73 | ipaddr.IPNetwork(data)
74 | return Prefix(data)
75 | except ValueError:
76 | pass
77 |
78 | raise ValueError('Cannot classify %s' % data)
79 |
80 |
--------------------------------------------------------------------------------
/irrexplorer/www.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # Copyright (c) 2015, Job Snijders
3 | # Copyright (c) 2015, NORDUnet A/S
4 | #
5 | # This file is part of IRR Explorer
6 | #
7 | # Redistribution and use in source and binary forms, with or without
8 | # modification, are permitted provided that the following conditions are met:
9 | #
10 | # 1. Redistributions of source code must retain the above copyright notice,
11 | # this list of conditions and the following disclaimer.
12 | #
13 | # 2. Redistributions in binary form must reproduce the above copyright notice,
14 | # this list of conditions and the following disclaimer in the documentation
15 | # and/or other materials provided with the distribution.
16 | #
17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 | # POSSIBILITY OF SUCH DAMAGE.
28 |
29 | from irrexplorer import utils, report
30 | from irrexplorer.utils import Prefix, ASNumber, ASMacro
31 |
32 | import json
33 |
34 | from flask import Flask, render_template, request, flash, redirect, url_for, send_from_directory
35 | from flask_bootstrap import Bootstrap
36 | from flask_wtf import Form
37 | from wtforms import TextField, SubmitField
38 | from wtforms.validators import Required
39 |
40 |
41 | class InputForm(Form):
42 | field = TextField('Data', description='Input ASN, AS-SET or Prefix.', validators=[Required()])
43 | submit_button = SubmitField('Submit')
44 |
45 |
46 | def create_app(pgdb, configfile=None):
47 | app = Flask('IRRExplorer')
48 | app.config.from_pyfile('appconfig.cfg')
49 | Bootstrap(app)
50 |
51 | @app.route("/robots.txt")
52 | def static_from_root():
53 | return send_from_directory(app.static_folder, request.path[1:])
54 |
55 | @app.route('/', methods=['GET', 'POST'])
56 | def index():
57 | form = InputForm()
58 | if request.method == 'GET':
59 | return render_template('index.html', form=form)
60 |
61 | if request.method == 'POST':
62 | # note: the form won't submit with empty data, so we don't have to handle that
63 | data = form.field.data
64 | print 'Form data:', data
65 |
66 | try:
67 | sv = utils.classifySearchString(data)
68 | return redirect(url_for('search', data=sv.value))
69 |
70 | except ValueError as e:
71 | flash('Invalid search data: ' + str(e))
72 | return render_template('index.html', form=form)
73 |
74 | # -- search --
75 | @app.route('/search/')
76 | @app.route('/search/', defaults={'data': None})
77 | @app.route('/search', defaults={'data': None})
78 | def search(data):
79 |
80 | query_data = request.args.get('data')
81 | if query_data:
82 | # this means that we got search request
83 | print 'query data', query_data
84 | return redirect(url_for('search', data=query_data))
85 |
86 | if not data:
87 | flash('No search data provided')
88 | return render_template('search.html')
89 |
90 | try:
91 | sv = utils.classifySearchString(data)
92 |
93 | # prevent people from killing the machine by searching through all prefixes in one query
94 | if type(sv) is Prefix and '/' in sv.value and int(sv.value.split('/',2)[-1]) < 15:
95 | flash('Only prefixes longer than /15 are searchable (kills the database)')
96 | return render_template('search.html')
97 |
98 | tables = []
99 |
100 | # page: title (object type : data)
101 |
102 | # json url for each table, not per report...
103 | # stuff that is needed per table:
104 | # id (tables.key)
105 | # name
106 | # source url
107 | # column ordering (first, and last, we cannot do complete until we get results)
108 | # note (optional)
109 |
110 | if type(sv) is Prefix:
111 | title = 'Prefix: ' + sv.value
112 | tables.append({
113 | 'id' : 'prefixes',
114 | 'title' : 'Matching prefixes',
115 | 'url' : '/json/prefix/' + sv.value,
116 | 'start_fields' : ["prefix", "bgp" ]
117 | })
118 |
119 | if type(sv) is ASNumber:
120 | title = 'AS Number: ' + data
121 | tables.append({
122 | 'id' : 'prefixes',
123 | 'title' : 'Prefixes',
124 | 'url' : '/json/as_prefixes/' + str(sv.value),
125 | 'start_fields' : ["prefix", "bgp" ],
126 | 'note' : 'Offending prefixes are only found if initial prefix sets is smaller than 1000'
127 | })
128 |
129 | if type(sv) is ASMacro:
130 | title = 'AS Macro: ' + data
131 | tables.append({
132 | 'id' : 'expanded',
133 | 'title' : 'Macro Expansion',
134 | 'url' : '/json/macro_expand/' + sv.value,
135 | 'start_fields' : ["as_macro", "depth", "path", "source", "members"],
136 | 'note' : 'AS Macro expansion is limited to 10K rows'
137 | })
138 |
139 | if type(sv) in (ASNumber, ASMacro):
140 | key = 'AS' + str(sv.value) if type(sv) is ASNumber else str(sv.value)
141 | tables.append({
142 | 'id' : 'macros',
143 | 'title' : 'Included in the following macros:',
144 | 'url' : '/json/macro_contain/' + key,
145 | 'start_fields' : ["as_macro" ]
146 | })
147 |
148 | return render_template('search.html', title=title, tables=tables)
149 |
150 |
151 | except ValueError as e:
152 | flash('Invalid search data: ' + str(e))
153 | return render_template('search.html')
154 |
155 |
156 | # -- json reports --
157 |
158 | @app.route('/json/prefix/')
159 | def prefix(prefix):
160 | data = report.prefix(pgdb, prefix)
161 | return json.dumps(data)
162 |
163 | @app.route('/json/as_prefixes/')
164 | def as_prefixes(as_number):
165 | data = report.as_prefixes(pgdb, int(as_number))
166 | return json.dumps(data)
167 |
168 | @app.route('/json/macro_expand/')
169 | def macro_expand(as_macro):
170 | data = report.macro_expand(pgdb, as_macro)
171 | return json.dumps(data)
172 |
173 | @app.route('/json/macro_contain/')
174 | def as_contain(as_object):
175 | data = report.macro_contain(pgdb, as_object)
176 | return json.dumps(data)
177 |
178 | return app
179 |
180 |
--------------------------------------------------------------------------------
/irrexplorer_config.yml.dist:
--------------------------------------------------------------------------------
1 | databases:
2 | - afrinic:
3 | - serial: 'ftp://ftp.afrinic.net/dbase/AFRINIC.CURRENTSERIAL'
4 | - dump: 'ftp://ftp.afrinic.net/dbase/afrinic.db.gz'
5 | - nrtmhost: 'rr.ntt.net'
6 | - nrtmport: 43
7 | - dbname: 'AFRINIC'
8 | - altdb:
9 | - serial: 'ftp://ftp.radb.net/radb/dbase/ALTDB.CURRENTSERIAL'
10 | - dump: 'ftp://ftp.radb.net/radb/dbase/altdb.db.gz'
11 | - nrtmhost: 'rr.ntt.net'
12 | - nrtmport: 43
13 | - dbname: 'ALTDB'
14 | - apnic:
15 | - serial: 'ftp://ftp.apnic.net/apnic/whois/APNIC.CURRENTSERIAL'
16 | - dump:
17 | - 'https://ftp.apnic.net/apnic/whois/apnic.db.as-set.gz'
18 | - 'https://ftp.apnic.net/apnic/whois/apnic.db.route.gz'
19 | - 'https://ftp.apnic.net/apnic/whois/apnic.db.route6.gz'
20 | - nrtmhost: 'rr.ntt.net'
21 | - nrtmport: 43
22 | - dbname: 'APNIC'
23 | - arin:
24 | - serial: 'ftp://ftp.radb.net/radb/dbase/ARIN.CURRENTSERIAL'
25 | - dump: 'ftp://ftp.radb.net/radb/dbase/arin.db.gz'
26 | - nrtmhost: 'rr.ntt.net'
27 | - nrtmport: 43
28 | - dbname: 'ARIN'
29 | - bboi:
30 | - serial: 'ftp://ftp.radb.net/radb/dbase/BBOI.CURRENTSERIAL'
31 | - dump: 'ftp://ftp.radb.net/radb/dbase/bboi.db.gz'
32 | - nrtmhost: 'rr.ntt.net'
33 | - nrtmport: 43
34 | - dbname: 'BBOI'
35 | - bell:
36 | - serial: 'ftp://ftp.radb.net/radb/dbase/BELL.CURRENTSERIAL'
37 | - dump: 'ftp://ftp.radb.net/radb/dbase/bell.db.gz'
38 | - nrtmhost: 'rr.ntt.net'
39 | - nrtmport: 43
40 | - dbname: 'BELL'
41 | - gt:
42 | - serial: 'ftp://ftp.radb.net/radb/dbase/GT.CURRENTSERIAL'
43 | - dump: 'ftp://ftp.radb.net/radb/dbase/gt.db.gz'
44 | - nrtmhost: 'rr.ntt.net'
45 | - nrtmport: 43
46 | - dbname: 'GT'
47 | - jpirr:
48 | - serial: 'ftp://ftp.radb.net/radb/dbase/JPIRR.CURRENTSERIAL'
49 | - dump: 'ftp://ftp.radb.net/radb/dbase/jpirr.db.gz'
50 | - nrtmhost: 'rr.ntt.net'
51 | - nrtmport: 43
52 | - dbname: 'JPIRR'
53 | - level3:
54 | - serial: 'ftp://ftp.radb.net/radb/dbase/LEVEL3.CURRENTSERIAL'
55 | - dump: 'ftp://ftp.radb.net/radb/dbase/level3.db.gz'
56 | - nrtmhost: 'rr.ntt.net'
57 | - nrtmport: 43
58 | - dbname: 'LEVEL3'
59 | - nttcom:
60 | - serial: 'ftp://ftp.radb.net/radb/dbase/NTTCOM.CURRENTSERIAL'
61 | - dump: 'ftp://ftp.radb.net/radb/dbase/nttcom.db.gz'
62 | - nrtmhost: 'rr.ntt.net'
63 | - nrtmport: 43
64 | - dbname: 'NTTCOM'
65 | - radb:
66 | - serial: 'ftp://ftp.radb.net/radb/dbase/RADB.CURRENTSERIAL'
67 | - dump: 'ftp://ftp.radb.net/radb/dbase/radb.db.gz'
68 | - nrtmhost: 'rr.ntt.net'
69 | - nrtmport: 43
70 | - dbname: 'RADB'
71 | - rgnet:
72 | - serial: 'ftp://ftp.radb.net/radb/dbase/RGNET.CURRENTSERIAL'
73 | - dump: 'ftp://ftp.radb.net/radb/dbase/rgnet.db.gz'
74 | - nrtmhost: 'rr.ntt.net'
75 | - nrtmport: 43
76 | - dbname: 'RGNET'
77 | - ripe:
78 | - serial: 'ftp://ftp.ripe.net/ripe/dbase/RIPE.CURRENTSERIAL'
79 | - dump:
80 | - ftp://ftp.ripe.net/ripe/dbase/split/ripe.db.route.gz
81 | - ftp://ftp.ripe.net/ripe/dbase/split/ripe.db.route6.gz
82 | - ftp://ftp.ripe.net/ripe/dbase/split/ripe.db.as-set.gz
83 | - nrtmhost: 'rr.ntt.net'
84 | - nrtmport: 43
85 | - dbname: 'RIPE'
86 | - tc:
87 | - serial: 'ftp://ftp.radb.net/radb/dbase/TC.CURRENTSERIAL'
88 | - dump: 'ftp://ftp.radb.net/radb/dbase/tc.db.gz'
89 | - nrtmhost: 'rr.ntt.net'
90 | - nrtmport: 43
91 | - dbname: 'TC'
92 |
--------------------------------------------------------------------------------
/irrexwww:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # Copyright (c) 2015, Job Snijders
3 | # Copyright (c) 2015, NORDUnet A/S
4 | #
5 | # This file is part of IRR Explorer
6 | #
7 | # Redistribution and use in source and binary forms, with or without
8 | # modification, are permitted provided that the following conditions are met:
9 | #
10 | # 1. Redistributions of source code must retain the above copyright notice,
11 | # this list of conditions and the following disclaimer.
12 | #
13 | # 2. Redistributions in binary form must reproduce the above copyright notice,
14 | # this list of conditions and the following disclaimer in the documentation
15 | # and/or other materials provided with the distribution.
16 | #
17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 | # POSSIBILITY OF SUCH DAMAGE.
28 |
29 | from irrexplorer import www, sqldb
30 |
31 |
32 |
33 | def main():
34 |
35 | dsn = "dbname=irrexplorer"
36 | pgdb = sqldb.IRRSQLDatabase(dsn)
37 |
38 | www.create_app(pgdb).run(host="0.0.0.0", debug=False, use_reloader=False)
39 |
40 |
41 |
42 | if __name__ == '__main__':
43 | main()
44 |
--------------------------------------------------------------------------------
/query:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # Copyright (c) 2015, NORDUnet A/S
3 |
4 | import sys
5 | from irrexplorer import utils, sqldb, report
6 |
7 |
8 | def main():
9 |
10 | if len(sys.argv) == 1:
11 | print "No argument given"
12 | sys.exit(1)
13 |
14 | dsn = "dbname=irrexplorer"
15 | db = sqldb.IRRSQLDatabase(dsn)
16 |
17 | for arg in sys.argv[1:]:
18 | try:
19 | so = utils.classifySearchString(arg)
20 |
21 | if type(so) is utils.Prefix:
22 | result = report.prefix(db, so.value)
23 | # prefix report already prints some stuff (consider changing that)
24 |
25 | if type(so) is utils.ASNumber:
26 | result = report.as_prefixes(db, so.value)
27 | for prefix, sources in result['prefixes'].items():
28 | print prefix, sources.keys()
29 | print
30 | for macro, sources in result['macros'].items():
31 | print macro, sources.keys()
32 |
33 | if type(so) is utils.ASMacro:
34 | #res = db.query_as_macro(so.value)
35 | result = report.macro_expand(db, so.value)
36 | for e in result['expanded']:
37 | print e
38 | print
39 | for macro, sources in result['macros'].items():
40 | print macro, ' '.join(sources.keys())
41 |
42 | except ValueError as e:
43 | print str(e)
44 |
45 |
46 | if __name__ == '__main__':
47 | main()
48 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | exabgp==3.4.7
2 | pyyaml
3 | ipaddr
4 | flask
5 | flask-bootstrap
6 | flask-table
7 | flask-wtf
8 | psycopg2
9 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [nosetests]
2 | verbosity=2
3 | detailed-errors=1
4 | with-coverage=1
5 | cover-package=irrexplorer
6 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # Copyright (C) 2015 Job Snijders
3 | #
4 | # This file is part of IRR Explorer
5 | #
6 | # Redistribution and use in source and binary forms, with or without
7 | # modification, are permitted provided that the following conditions are met:
8 | #
9 | # 1. Redistributions of source code must retain the above copyright notice,
10 | # this list of conditions and the following disclaimer.
11 | #
12 | # 2. Redistributions in binary form must reproduce the above copyright notice,
13 | # this list of conditions and the following disclaimer in the documentation
14 | # and/or other materials provided with the distribution.
15 | #
16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 | # POSSIBILITY OF SUCH DAMAGE.
27 |
28 | import irrexplorer
29 | version = irrexplorer.__version__
30 |
31 | import codecs
32 | import os
33 | import sys
34 |
35 | from pip.req import parse_requirements
36 | from setuptools import setup, find_packages
37 | from os.path import abspath, dirname, join
38 |
39 | here = abspath(dirname(__file__))
40 |
41 | with codecs.open(join(here, 'README.md'), encoding='utf-8') as f:
42 | README = f.read()
43 |
44 | if sys.argv[-1] == 'publish':
45 | os.system('python2.7 setup.py sdist upload')
46 | print("You probably want to also tag the version now:")
47 | print(" git tag -a %s -m 'version %s'" % (version, version))
48 | print(" git push --tags")
49 | sys.exit()
50 |
51 | install_reqs = parse_requirements('requirements.txt', session="")
52 | reqs = [str(ir.req) for ir in install_reqs]
53 |
54 |
55 | def get_data_files():
56 | man_path = '/usr/share/man/man7'
57 | if os.getenv('TRAVIS_BUILD_ID'):
58 | print "not installing manpage and conffile in travis environment"
59 | elif os.path.exists(man_path):
60 | files = [('/etc/irrexplorer', ['irrexplorer/doc/irrexplorer.conf.dist'])]
61 | files += [(man_path, ['irrexplorer/doc/irrexplorer.7'])]
62 | return files
63 |
64 | setup(
65 | name='irrexplorer',
66 | version=version,
67 | maintainer="Job Snijders",
68 | maintainer_email='job@instituut.net',
69 | url='https://github.com/job/irrexplorer',
70 | description='IRR data explorer',
71 | long_description=README,
72 | license='BSD 2-Clause',
73 | keywords='irr python bgp routing networking',
74 | classifiers=[
75 | 'Intended Audience :: Developers',
76 | 'Topic :: Software Development :: Libraries :: Python Modules',
77 | 'Topic :: System :: Networking',
78 | 'License :: OSI Approved :: BSD License',
79 | 'Programming Language :: Python :: 2.7',
80 | ],
81 | setup_requires=['nose', 'coverage'] + reqs,
82 | packages=find_packages(exclude=['tests', 'tests.*']),
83 | test_suite='nose.collector',
84 | entry_points={'console_scripts': ['irrexplorer = irrexplorer.cli:main']},
85 | data_files=get_data_files()
86 | )
87 |
--------------------------------------------------------------------------------
/static/img/false.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/job/irrexplorer/0af6f13b6b81d6dc66e8a1015ec428773d08c17d/static/img/false.png
--------------------------------------------------------------------------------
/static/img/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/job/irrexplorer/0af6f13b6b81d6dc66e8a1015ec428773d08c17d/static/img/loading.gif
--------------------------------------------------------------------------------
/static/img/true.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/job/irrexplorer/0af6f13b6b81d6dc66e8a1015ec428773d08c17d/static/img/true.png
--------------------------------------------------------------------------------
/static/js/table.js:
--------------------------------------------------------------------------------
1 | // generic table fill code for IRRExplorer
2 |
3 | function state_loaded() {
4 | $("#btnsearch").prop("disabled",false);
5 | $("#loading").hide();
6 | $("#btnsearch").html('Search');
7 | }
8 |
9 | function state_loading() {
10 | $("#btnsearch").prop("disabled",true);
11 | $("#btnsearch").html('Searching...');
12 | $("#loading").show();
13 | }
14 |
15 | // TODO: switch fieldname and data as I find the order rather confusing (htj)
16 | function renderCell(data, fieldname, label) {
17 |
18 | console.log("renderCell: " + data + " " + fieldname + " " + label);
19 | if (typeof data != 'undefined') {
20 | switch (data.toString()) {
21 | case "true":
22 | return "
";
23 | case "false":
24 | return "
";
25 | default:
26 | if (fieldname == "advice") {
27 | console.log(label);
28 | return "" + data + "";
29 | } else if (fieldname == "bgp") {
30 | return "" + data + "";
31 | } else if (fieldname == "path") {
32 | return data.join(" ➔ ");
33 | } else if (fieldname == "members") {
34 | var r = [];
35 | for (var idx in data) {
36 | r.push('' + data[idx] + '');
37 | }
38 | return r.join(" ");
39 | }
40 | else {
41 | return data;
42 | }
43 | }
44 | } else {
45 | return "";
46 | }
47 | }
48 |
49 |
50 | function getfields(table_data, start_fields) {
51 |
52 | var table_keys = Object.keys(table_data);
53 |
54 | var fields = start_fields.slice(0); // clone
55 |
56 | var last_fields = [];
57 |
58 | for (var idx in table_keys) {
59 | var key = table_keys[idx];
60 | var table_entry = table_data[key];
61 |
62 | var entry_fields = Object.keys(table_entry);
63 |
64 | for (var efi in entry_fields) {
65 | field_name = entry_fields[efi];
66 | if (field_name == "label") {
67 | continue; // this is reserved for coloring of advice
68 | }
69 | if (field_name == "advice") {
70 | if (last_fields.indexOf(field_name) == -1) {
71 | last_fields.push(field_name);
72 | }
73 | continue;
74 | }
75 | if (fields.indexOf(field_name) == -1) {
76 | fields.push(field_name);
77 | }
78 | }
79 | }
80 | fields = fields.concat(last_fields);
81 |
82 | return fields;
83 | }
84 |
85 | function populatetable(table_name, table_data, start_fields) {
86 |
87 | console.log("populate table: " + table_name);
88 | console.log(table_data);
89 | console.log(start_fields);
90 | console.log("--");
91 |
92 | fields = getfields(table_data, start_fields);
93 | console.log("fields: " + fields);
94 |
95 | $(table_name).hide();
96 |
97 | rows = [];
98 | table_keys = Object.keys(table_data);
99 |
100 | console.log(table_keys);
101 |
102 | for (var idx in table_keys) {
103 | key = table_keys[idx];
104 | console.log(key);
105 |
106 | table_entry = table_data[key];
107 | console.log(table_entry);
108 |
109 | if($.isArray(table_data)) {
110 | // useless index, change to first
111 | console.log(table_entry);
112 | key = table_entry[start_fields[0]];
113 | console.log(key);
114 | }
115 |
116 | row = [];
117 | for (var f in fields) {
118 | field = fields[f];
119 | if (field == start_fields[0]) {
120 | row.push('' + key + '');
121 | }
122 | else {
123 | var label;
124 | if (field == "bgp") {
125 | label = key;
126 | }
127 | else if (field == "advice") {
128 | label = table_entry["label"];
129 | }
130 | row.push(renderCell(table_entry[field], field, label));
131 | }
132 | }
133 | rows.push(row);
134 | };
135 |
136 | colsdisp = [];
137 | for (var f in fields) {
138 | field = fields[f];
139 | coldisp = {"title": field}
140 | colsdisp.push(coldisp);
141 | }
142 | // TODO: don't do the columnDefs if first row is not a prefix...
143 | if ( ! $.fn.DataTable.isDataTable(table_name) ) {
144 | var table= {
145 | "data": rows,
146 | "columns": colsdisp,
147 | "searching": false,
148 | "lengthChange": false,
149 | "bPaginate": false
150 | };
151 | if (start_fields[0] == "prefix") {
152 | table["columnDefs"] = [ { 'type': 'ip-address', 'targets': 0 } ];
153 | }
154 | if (start_fields[1] == "depth") { // order by depth if it exists (as macro expansion)
155 | table["order"] = [[ 1, "asc" ]]
156 | }
157 | $(table_name).dataTable(table);
158 | } else {
159 | // just update, already set the table up once
160 | $(table_name).dataTable().fnClearTable();
161 | $(table_name).dataTable().fnAddData(rows);
162 |
163 | }
164 |
165 | $(table_name).show();
166 | }
167 |
168 |
--------------------------------------------------------------------------------
/static/robots.txt:
--------------------------------------------------------------------------------
1 | User-Agent: *
2 | Disallow:
3 | Disallow: /search
4 | Disallow: /json
5 |
--------------------------------------------------------------------------------
/templates/index.html:
--------------------------------------------------------------------------------
1 | {% extends "bootstrap/base.html" %}
2 | {% import "bootstrap/wtf.html" as wtf %}
3 | {% import "bootstrap/fixes.html" as fixes %}
4 | {% import "bootstrap/utils.html" as util %}
5 |
6 | {% block styles %}
7 | {{super()}}
8 |
22 | {% endblock %}
23 |
24 | {% block content %}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |

35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | Enter an IP address, prefix, AS Number, or AS-SET
44 | {{ wtf.quick_form(form, form_type='inline', button_map={'submit_button': 'primary'}) }}
45 |
46 | {% for message in get_flashed_messages() %}
47 | {{ message }}
48 | {% endfor %}
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
66 | {% endblock %}
67 |
68 | {% block head %}
69 | {{super()}}
70 | {{fixes.ie8()}}
71 | {% endblock %}
72 |
--------------------------------------------------------------------------------
/templates/search.html:
--------------------------------------------------------------------------------
1 | {% extends "bootstrap/base.html" %}
2 | {% import "bootstrap/wtf.html" as wtf %}
3 | {% import "bootstrap/fixes.html" as fixes %}
4 | {% import "bootstrap/utils.html" as util %}
5 |
6 | {% block styles %}
7 | {{super()}}
8 |
31 |
32 | {% endblock %}
33 |
34 | {% block content %}
35 |
36 |
37 |
38 |
39 |
40 |
45 |
46 |
47 |
48 |
53 | {% for message in get_flashed_messages() %}
54 |
{{ message }}
55 | {% endfor %}
56 |
57 |
58 |
59 |
60 |
{{ title }}
61 |
62 |
63 |
64 |
67 |
68 |
69 | {% for table in tables %}
70 |
{{ table.title }}
71 |
72 |
73 | {% if table.note %}
74 |
{{ table.note }}
75 | {% endif %}
76 |
77 |
78 | {% endfor %}
79 |
80 |
81 |
82 |
83 |
84 | Source code available on
Github.
85 |
86 |
87 |
88 |
89 |
90 | {% endblock %}
91 |
92 | {% block scripts %}
93 | {{super()}}
94 |
95 |
96 |
152 | {% endblock %}
153 |
154 | {% block head %}
155 | {{super()}}
156 | {{fixes.ie8()}}
157 |
158 | {% endblock %}
159 |
--------------------------------------------------------------------------------
/tests/REGRESSION.CURRENTSERIAL:
--------------------------------------------------------------------------------
1 | 1983028
--------------------------------------------------------------------------------
/tests/irrtest.data:
--------------------------------------------------------------------------------
1 | route: 207.72.0.0/14
2 | descr: MERIT Network Inc.
3 | 1000 Oakbrook Drive, Suite 200
4 | Ann Arbor
5 | MI 48104, USA
6 | origin: AS237
7 | mnt-by: MAINT-AS237
8 | changed: rik@merit.edu 20050922
9 | source: RADB
10 |
11 | % RIPE style comments
12 | % hi
13 |
14 | as-set: AS-test1
15 | descr: Stub ASs for ClubNET
16 | members: AS5726, AS5736, AS20318
17 | admin-c: DG251
18 | tech-c: PC41
19 | notify: route@ns.clubnet.net
20 | mnt-by: MAINT-AS5736-ALTDB
21 | changed: pete@altadena.net 20010713
22 | source: ALTDB
23 |
24 | person: Job Snijders
25 | address: Theodorus Majofskistraat 100
26 | address: 1065 SZ Amsterdam
27 | address: The Netherlands
28 | remarks: PGP key is PGPKEY-7E5BEC10
29 | phone: +31-6-54942365
30 | nic-hdl: JWJS1-RIPE
31 | mnt-by: SNIJDERS-MNT
32 | source: RIPE # Filtered
33 |
34 | as-set: AS-test2
35 | descr: Stub ASs for ClubNET
36 | members: AS5726
37 | members: AS5736, AS20318
38 | admin-c: DG251
39 | tech-c: PC41
40 | notify: route@ns.clubnet.net
41 | mnt-by: MAINT-AS5736-ALTDB
42 | changed: pete@altadena.net 20010713
43 | source: ALTDB
44 |
45 | as-set: AS-test3
46 | descr: Stub ASs for ClubNET
47 | members: AS5726
48 | members: AS5736, AS20318 # herpa
49 | admin-c: DG251
50 | tech-c: PC41
51 | notify: route@ns.clubnet.net
52 | mnt-by: MAINT-AS5736-ALTDB
53 | changed: pete@altadena.net 20010713
54 | source: ALTDB
55 |
56 | as-set: AS-PACIFIC-INTERNET-IX
57 | descr: Pacific Internet Malaysia
58 | c/o 89 Science Park Drive
59 | #02-05/06 Rutherford
60 | Singapore 118261
61 | Republic of Singapore
62 | Tel: +65-6872-1010
63 | Fax: +65-6872-1011
64 | members: AS4628, AS4629
65 | remarks: Peering with AS4628 and AS4629
66 | Email abuse@pacific.net.sg for security issues
67 | Email noc@pacific.net.sg for network issues
68 | admin-c: WH1-AP
69 | tech-c: WH1-AP
70 | notify: noc@pacific.net.sg
71 | mnt-by: MAINT-AS9904
72 | changed: hoou@pacific.net.sg 20020328
73 | source: ALTDB
74 |
75 | as-set: AS-NIXC
76 | descr: ASNs announced by NIXC.
77 | members: AS-NIXC-BACKBONE, AS-NIXC-CUSTOMERS
78 | admin-c: Darrin Walton
79 | tech-c: Darrin Walton
80 | notify: radb@nixc.net
81 | mnt-by: MAINT-NIXC
82 | changed: darrinw@nixc.net 20020801
83 | source: ALTDB
84 |
85 | as-set: AS5042:AS-PEERS
86 | descr: IWT Peers
87 | members: AS3638, AS8001, AS5430, AS9156, AS13768, AS10588
88 | admin-c: LNK
89 | tech-c: LNK
90 | notify: noc@informationwave.net
91 | mnt-by: MAINT-AS5042
92 | changed: missnglnk@informationwave.net 20021013
93 | source: ALTDB
94 |
95 | as-set: AS-CABOTELECOM-CUST-IPv6
96 | descr: Customers from Cabo Telecom.
97 | members: AS28339 # ACT
98 | members: AS262857 # UFRN
99 | members: AS262876 # UNP
100 | tech-c: ARCTE-LACNIC
101 | admin-c: ARCTE-LACNIC
102 | notify: noc@cabotelecom.com.br
103 | mnt-by: CABONATAL-BR
104 | changed: eduardo.andrez@cabotelecom.com.br 20110403
105 | source: ALTDB
106 |
107 | as-set: AS-NLAYER-CUSTOMERS
108 | descr: nLayer Communications - Customer AS-SET
109 | members: AS10625, AS10692, AS10905, AS10940, AS11013, AS11280, AS11282,
110 | AS11346, AS11478, AS11483, AS11682, AS11696, AS11763, AS11931,
111 | AS-1215, AS12284, AS13335, AS1341, AS13557, AS13722, AS13730,
112 | AS13803, AS1403, AS14061, AS14193, AS14200, AS1421, AS14288,
113 | AS1442, AS14601, AS14627, AS14670, AS14829, AS14929, AS14987,
114 | AS15024, AS15072, AS15149, AS15266, AS15695, AS16162, AS16626,
115 | AS16632, AS16647, AS16839, AS16986, AS17139, AS17246, AS18549,
116 | AS18608, AS18787, AS18793, AS18978, AS18981, AS19066, AS19222,
117 | AS19230, AS19245, AS19551, AS197669, AS197853, AS199636, AS19970,
118 | AS199799, AS20144, AS20223, AS21267, AS21321, AS21534, AS21797,
119 | AS21840, AS22300, AS22518, AS22543, AS22653, AS22915, AS23136,
120 | AS23367, AS23421, AS23498, AS23522, AS23533, AS236, AS24894,
121 | AS25151, AS25605, AS25764, AS25780, AS25782, AS25844, AS26288,
122 | AS26342, AS26424, AS26449, AS26484, AS26548, AS26642, AS26697,
123 | AS26938, AS26967, AS26972, AS27280, AS27381, AS27413,
124 | AS-27506-TRANSIT, AS27908, AS28786, AS29706, AS29846, AS29909,
125 | AS30058, AS30238, AS30373, AS30502, AS-30517-ASSOCIATED, AS31402,
126 | AS32063, AS32131, AS32286, AS32313, AS32392,
127 | AS32421:AS-CUSTOMERS, AS32489, AS32632, AS32780, AS32782,
128 | AS32977, AS33065, AS33314, AS33404, AS34967, AS35180, AS3584,
129 | AS35890, AS35906, AS3595, AS35975, AS36137, AS36323, AS36605,
130 | AS36614, AS3737, AS376:AS-CUSTOMERS, AS3842, AS38880, AS393241,
131 | AS3943, AS39995, AS40041, AS40125, AS40217, AS40335, AS40353,
132 | AS40418, AS40428, AS40539, AS40676, AS40784, AS40926, AS42369,
133 | AS43639, AS43664, AS44965, AS4544:AS-NA-CUSTOMERS, AS45474,
134 | AS46261, AS46351, AS46489, AS46609, AS46652, AS46665, AS46844,
135 | AS46922, AS47484, AS4866, AS50468, AS51205, AS53265, AS53301,
136 | AS53342, AS53428, AS53429, AS53582, AS53817, AS53969, AS54113,
137 | AS54136, AS54235, AS54288, AS54329, AS54333, AS54335, AS54460,
138 | AS54491, AS54527:AS-GLOBAL, AS54540, AS54594, AS54600, AS54778,
139 | AS54829, AS54905, AS54953, AS54957, AS54963, AS54994, AS55011,
140 | AS55041, AS55069, AS5645:AS-CUSTOMERS, AS-5713, AS57624, AS5784,
141 | AS60736, AS61373, AS62195, AS62567, AS62713, AS62725, AS62870,
142 | AS62982, AS63003, AS63008, AS63058, AS6643, AS7219, AS7456,
143 | AS792, AS-ACEDATACENTERS, AS-ACN, AS-ADTAQ, AS-AFILIAS-FULLMONTY,
144 | AS-AFNCA, AS-AKAMAI, AS-APPLIEDOPS, AS-AREN, AS-ARIALINK,
145 | AS-AVESTANETWORKS, AS-BIGWELLS, AS-BLIP, AS-BTS, AS-BURSTNET,
146 | AS-BXI, AS-C1, AS-C3, AS-CACHENETWORKS, AS-CBISP, AS-CHOOPA,
147 | AS-CIFNET, AS-CLUETRUST, AS-CNSERVERS, AS-COGNET, AS-COLOAT,
148 | AS-COLOCROSSING, AS-CORESITE-SET, AS-CQ-GIGENET, AS-CYBERVERSE,
149 | AS-DACENTEC, AS-DCC, AS-DEAC, AS-DISTRIBUTEL, AS-DVLABS,
150 | AS-ED-ASH, AS-EDGECAST, AS-ENA, AS-ENERGYGROUPNETWORKS,
151 | AS-FIBERINTERNETCENTER, AS-FORTRESS, AS-FOXVALLEY,
152 | AS-GIGANEWS-ALL, AS-GORACK, AS-GREATACCESS, AS-GTCOMM1,
153 | AS-HAPNET, AS-HGC, AS-HOSTVIRTUAL, AS-ICANNDNSW, AS-IDCGLOBAL,
154 | AS-INFORELAY, AS-INFOSTEWARDS, AS-INMOTION, AS-INTERACTIVE3D,
155 | AS-VIO, AS-VOBIZ, AS-VOXEL, AS-VPLS, AS-WBTSGBR, AS-WEBAIR,
156 | AS-WEBNX, AS-WEBPASS, AS-WESTHOST, AS-WHS-US, AS-XMISSION,
157 | AS-XPLUSONE, AS-YELLOWFIBER, AS-YOUR-GLOBAL-SET
158 | admin-c: NIA1-ARIN
159 | tech-c: NLAYE-ARIN
160 | mnt-by: MAINT-NLAYER
161 | changed: ipeng@nlayer.net 20150208
162 | source: ALTDB
163 |
164 | as-set: AS-NLAYER-CUSTOMERS2
165 | descr: nLayer Communications - Customer AS-SET
166 | members: AS10625, AS10692, AS10905, AS10940, AS11013, AS11280, AS11282,
167 | AS11346, AS11478, AS11483, AS11682, AS11696, AS11763, AS11931,
168 | AS-1215, AS12284, AS13335, AS1341, AS13557, AS13722, AS13730,
169 | AS-BXI, AS-C1, AS-C3, AS-CACHENETWORKS, AS-CBISP, AS-CHOOPA,
170 | AS-CIFNET, AS-CLUETRUST, AS-CNSERVERS, AS-COGNET, AS-COLOAT,
171 | AS-COLOCROSSING, AS-CORESITE-SET, AS-CQ-GIGENET, AS-CYBERVERSE, # herpa
172 | AS-XPLUSONE, AS-YELLOWFIBER, AS-YOUR-GLOBAL-SET #derpa
173 | admin-c: NIA1-ARIN
174 | tech-c: NLAYE-ARIN
175 | mnt-by: MAINT-NLAYER
176 | changed: ipeng@nlayer.net 20150208
177 | source: ALTDB
178 |
179 | # EOF
180 |
--------------------------------------------------------------------------------
/tests/nrtm_server.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # Copyright (C) 2015 Job Snijders
3 | #
4 | # This file is part of IRR Explorer
5 | #
6 | # Redistribution and use in source and binary forms, with or without
7 | # modification, are permitted provided that the following conditions are met:
8 | #
9 | # 1. Redistributions of source code must retain the above copyright notice,
10 | # this list of conditions and the following disclaimer.
11 | #
12 | # 2. Redistributions in binary form must reproduce the above copyright notice,
13 | # this list of conditions and the following disclaimer in the documentation
14 | # and/or other materials provided with the distribution.
15 | #
16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | # ARISING IN ANY WAY OUT OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 | # POSSIBILITY OF SUCH DAMAGE.
27 |
28 | """
29 | Small script to emulate a NRTM server
30 | Copyright (C) 2015 Job Snijders
31 |
32 | Registry name: REGRESSION :-)
33 |
34 | Get a sample or NRTM:
35 | echo -k -g RADB:3:$(echo $(curl -s \
36 | ftp://ftp.radb.net/radb/dbase/RADB.CURRENTSERIAL) - 5 | bc)-LAST \
37 | | nc whois.radb.net 43
38 |
39 | """
40 |
41 | import time
42 | import socket
43 | from thread import start_new_thread
44 |
45 | host = '::'
46 | port = 4444
47 | flowinfo = 0
48 | scopeid = 0
49 | sockaddr = (host, port, flowinfo, scopeid)
50 |
51 | nrtm_data_1 = """%START Version: 3 regression 1983029-1983034
52 |
53 | ADD 1983029
54 |
55 | route: 180.211.93.0/24
56 | descr: route-object of PT. KINGS NETWORK INDONESIA
57 | Internet Services Provider
58 | Bekasi, ID
59 | origin: AS45725
60 | notify: windhu@i.net.id
61 | mnt-by: MAINT-AS45725
62 | changed: windhu@i.net.id 20150209 #11:51:47Z
63 | source: REGRESSION
64 |
65 | ADD 1983030
66 |
67 | route: 180.211.92.0/24
68 | descr: route-object of PT. KINGS NETWORK INDONESIA
69 | Internet Services Provider
70 | Bekasi, ID
71 | origin: AS45725
72 | notify: windhu@i.net.id
73 | mnt-by: MAINT-AS45725
74 | changed: windhu@i.net.id 20150209 #11:52:15Z
75 | source: REGRESSION
76 |
77 | ADD 1983031
78 |
79 | mntner: MAINT-AS198492
80 | descr: rPeer Ltd
81 | admin-c: Denis Nuja
82 | tech-c: Denis Nuja
83 | upd-to: denis@falizmaj.org
84 | mnt-nfy: denis@falizmaj.org
85 | auth: CRYPT-PW HIDDENCRYPTPW
86 | mnt-by: MAINT-AS198492
87 | changed: e@e.net 20150203
88 | source: REGRESSION
89 |
90 | ADD 1983032
91 |
92 | aut-num: AS198492
93 | as-name: RPEER-1
94 | descr: rPeer Ltd
95 | admin-c: Denis Nuja
96 | tech-c: Denis Nuja
97 | mnt-by: MAINT-AS198492
98 | changed: d@d.net
99 | source: REGRESSION
100 |
101 | ADD 1983033
102 |
103 | route: 91.235.170.0/23
104 | descr: rPeer Ltd
105 | origin: AS198492
106 | mnt-by: MAINT-AS198492
107 | changed: d@d.com
108 | source: REGRESSION
109 |
110 | ADD 1983034
111 |
112 | aut-num: AS198492
113 | as-name: RPEER-1
114 | descr: rPeer Ltd
115 | import: from AS174 accept any
116 | import: from AS9119 accept any
117 | import: from AS198785 accept any
118 | export: to AS174 announce AS198492
119 | export: to AS9119 announce AS198492
120 | export: to AS198785 announce AS198492
121 | admin-c: Denis Nuja
122 | tech-c: Denis Nuja
123 | mnt-by: MAINT-AS198492
124 | changed: d@d.com
125 | source: REGRESSION
126 |
127 | %END REGRESSION
128 | """
129 |
130 | nrtm_data_2 = """
131 | ADD 1983035
132 |
133 | route: 5.8.47.0/24
134 | descr: Depo Data Center
135 | origin: AS50896
136 | mnt-by: MNT-DEPO40
137 | changed: unread@ripe.net 20000101
138 | source: REGRESSION
139 | remarks: ****************************
140 | remarks: * THIS OBJECT IS MODIFIED
141 | remarks: * Please note that all data that is generally regarded as personal
142 | remarks: * data has been removed from this object.
143 | remarks: * To view the original object, please query the RIPE Database at:
144 | remarks: * http://www.ripe.net/whois
145 | remarks: ****************************
146 |
147 | """
148 |
149 |
150 | def clientthread(conn):
151 | conn.send('% Welcome to the NRTM test server.\n\n')
152 | while True:
153 | data = conn.recv(1024).strip()
154 | if not data:
155 | break
156 | print data
157 | if data == "-k -g REGRESSION:3:1983029-LAST":
158 | # send feed (copied from RADB)
159 | print "sending:"
160 | print nrtm_data_1
161 | conn.sendall(nrtm_data_1)
162 | # keep socket open, act like persistent
163 | time.sleep(10)
164 | # client requested refresh, but instead gets latest object
165 | print "sending:"
166 | print nrtm_data_2
167 | conn.sendall(nrtm_data_2)
168 | time.sleep(1)
169 | conn.close()
170 | if data == "!q":
171 | conn.close()
172 | conn.close()
173 |
174 | if __name__ == "__main__":
175 | sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM, 0)
176 | sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
177 | sock.bind(sockaddr)
178 | sock.listen(10)
179 | while True:
180 | conn, addr = sock.accept()
181 | print 'Connected with ' + addr[0] + ':' + str(addr[1])
182 | start_new_thread(clientthread, (conn,))
183 | sock.close()
184 |
--------------------------------------------------------------------------------
/tests/nrtm_test.yml:
--------------------------------------------------------------------------------
1 | databases:
2 | regression:
3 | serial: 'tests/REGRESSION.CURRENTSERIAL'
4 | dump: 'tests/irrtest.data'
5 | nrtmhost: 'localhost'
6 | nrtmport: 4444
7 |
--------------------------------------------------------------------------------
/tests/test_nrtmclient.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # Copyright (C) 2015 Job Snijders
3 | #
4 | # This file is part of IRR Explorer
5 | #
6 | # Redistribution and use in source and binary forms, with or without
7 | # modification, are permitted provided that the following conditions are met:
8 | #
9 | # 1. Redistributions of source code must retain the above copyright notice,
10 | # this list of conditions and the following disclaimer.
11 | #
12 | # 2. Redistributions in binary form must reproduce the above copyright notice,
13 | # this list of conditions and the following disclaimer in the documentation
14 | # and/or other materials provided with the distribution.
15 | #
16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | # ARISING IN ANY WAY OUT OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 | # POSSIBILITY OF SUCH DAMAGE.
27 |
28 | import unittest
29 |
30 | from irrexplorer import nrtm, config
31 |
32 |
33 | class TestNRTM(unittest.TestCase):
34 | def test_00__test_nrtm(self):
35 | feedconfig = config('tests/nrtm_test.yml').databases['regression']
36 | feed = nrtm.client(**feedconfig)
37 | for cmd, serial, obj in feed.get():
38 | if not obj:
39 | continue
40 | print cmd, serial, len(obj)
41 | if cmd == "ADD" and serial == 1983035 and len(obj) == 4:
42 | self.assertTrue(True)
43 |
44 | def main():
45 | unittest.main()
46 |
47 | if __name__ == '__main__':
48 | main()
49 |
--------------------------------------------------------------------------------
/tests/test_regression.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # Copyright (C) 2015 Job Snijders
3 | #
4 | # This file is part of IRR Explorer
5 | #
6 | # Redistribution and use in source and binary forms, with or without
7 | # modification, are permitted provided that the following conditions are met:
8 | #
9 | # 1. Redistributions of source code must retain the above copyright notice,
10 | # this list of conditions and the following disclaimer.
11 | #
12 | # 2. Redistributions in binary form must reproduce the above copyright notice,
13 | # this list of conditions and the following disclaimer in the documentation
14 | # and/or other materials provided with the distribution.
15 | #
16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | # ARISING IN ANY WAY OUT OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 | # POSSIBILITY OF SUCH DAMAGE.
27 |
28 | from __future__ import print_function, division, absolute_import, unicode_literals
29 |
30 | import unittest
31 |
32 | from irrexplorer import parser
33 |
34 |
35 | class TestIRRExplorer(unittest.TestCase):
36 | def test_00__parse_rpsl_dump(self):
37 | dump = open('tests/irrtest.data')
38 | self.assertTrue(list(parser.parse_dump(dump)))
39 |
40 |
41 | def main():
42 | unittest.main()
43 |
44 | if __name__ == '__main__':
45 | main()
46 |
--------------------------------------------------------------------------------
/tests/test_utils.py:
--------------------------------------------------------------------------------
1 | # test classification
2 |
3 | import unittest
4 |
5 | from irrexplorer import utils
6 |
7 |
8 | class TestClassification(unittest.TestCase):
9 |
10 | def test_classification(self):
11 |
12 | a = utils.classifySearchString('10.0.0.1')
13 | self.assertEquals(type(a), utils.Prefix)
14 |
15 | a = utils.classifySearchString('1.3.4.0/24')
16 | self.assertEquals(type(a), utils.Prefix)
17 |
18 | a = utils.classifySearchString('AS2603')
19 | self.assertEquals(type(a), utils.ASNumber)
20 |
21 | a = utils.classifySearchString('AS-NTT')
22 | self.assertEquals(type(a), utils.ASMacro)
23 |
24 | a = utils.classifySearchString('AS-57344')
25 | self.assertEquals(type(a), utils.ASMacro)
26 |
27 | a = utils.classifySearchString('AS9498:AS-BHARTI-IN')
28 | self.assertEquals(type(a), utils.ASMacro)
29 |
30 |
31 |
32 |
33 | def main():
34 | unittest.main()
35 |
36 |
37 | if __name__ == '__main__':
38 | main()
39 |
40 |
--------------------------------------------------------------------------------
/worker:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Script to update BGP and IRR entries in the IRRExplorer database.
5 | """
6 |
7 | import os
8 | import time
9 | import argparse
10 | import logging
11 |
12 | import yaml
13 |
14 | from irrexplorer import sqldb, bgpupdate, irrupdate
15 |
16 |
17 | DEFAULT_DATABASE = 'irrexplorer'
18 | DEFAULT_BGP_SOURCE = 'http://lg01.infra.ring.nlnog.net/table.txt'
19 | DEFAULT_IRR_SPEC = 'irrexplorer_config.yml'
20 | DEFAULT_LOG_FILE = 'irrworker.log'
21 |
22 | DEFAULT_UPDATE_INTERVAL = 300 # 5 minutes, the nlnog table is updated at that frequency
23 |
24 |
25 | INSERT_STM = "SELECT create_route (%s, %s, 'bgp');"
26 | DELETE_STM = "DELETE FROM routes USING sources WHERE routes.route = %s AND routes.asn = %s AND routes.source_id = sources.id AND sources.name = 'bgp';"
27 |
28 |
29 |
30 | def create_parser():
31 |
32 | parser = argparse.ArgumentParser(description='Continously update BGP table in IRRExplorer database')
33 | parser.add_argument('-b', '--bgp-source', dest='bgp_source', default=DEFAULT_BGP_SOURCE, help='Source URL for BGP routing table (default: nlnog ring table)')
34 | parser.add_argument('-r', '--irr-spec', dest='irr_spec', default=DEFAULT_IRR_SPEC, help='IRR specifications file (default: %s)' % DEFAULT_IRR_SPEC)
35 | parser.add_argument('-d', '--database', dest='database', default=DEFAULT_DATABASE, help='IRRExplorer database name (default: %s)' % DEFAULT_DATABASE)
36 | parser.add_argument('-i', '--interval', dest='interval', default=DEFAULT_UPDATE_INTERVAL, help='Interval between updates (default: %i seconds)' % DEFAULT_UPDATE_INTERVAL)
37 | parser.add_argument('-l', '--logfile', dest='logfile', default=DEFAULT_LOG_FILE, help='Log file (default: %s)' % DEFAULT_LOG_FILE)
38 | return parser
39 |
40 |
41 |
42 | def parse_irr_spec(irr_spec):
43 |
44 | specs = []
45 |
46 | if not os.path.exists(irr_spec):
47 | print 'Error: IRR spec file does not exist'
48 | return specs # don't fail on this (bgp update should be allowed to run)
49 |
50 | irr_cfg = open(irr_spec)
51 | cfg = yaml.load(irr_cfg)
52 |
53 | for db in cfg['databases']:
54 | for db_name, db_info in db.items():
55 | host = port = source = None
56 | for dbe in db_info:
57 | host = dbe.get('nrtmhost', host)
58 | port = dbe.get('nrtmport', port)
59 | source = dbe.get('dbname', source)
60 |
61 | if host and source:
62 | specs.append( (host, port, source) )
63 | else:
64 | print 'Could not parse %s for NRTM info' % db_name
65 |
66 | return specs
67 |
68 |
69 |
70 | def main():
71 |
72 | parser = create_parser()
73 | args = parser.parse_args()
74 |
75 | update_interval = int(args.interval)
76 |
77 | irr_sources = parse_irr_spec(args.irr_spec)
78 |
79 | logging.basicConfig(filename=args.logfile, format='%(asctime)s %(levelname)s: %(message)s', level=logging.DEBUG)
80 |
81 | dsn = 'dbname=%s' % args.database
82 | db = sqldb.IRRSQLDatabase(dsn)
83 |
84 | logging.info('Worker started')
85 |
86 | while True:
87 |
88 | t_start = time.time()
89 |
90 | # bgp
91 | try:
92 | bgpupdate.updateBGP(args.bgp_source, db)
93 | except Exception as e:
94 | logging.error('Error duing bgp update: %s' % str(e))
95 |
96 | # irr update
97 | for host, port, source in irr_sources:
98 | try:
99 | irrupdate.update_irr(host, port, source, db)
100 | except Exception as e:
101 | logging.error('Error during IRR update: %s' % str(e))
102 | if "don't exist!" in str(e):
103 | logging.error(
104 | "ERROR: the above error probably means that the gap between your seed" +
105 | "snapshot and the current SERIAL on the stream source is too large.")
106 |
107 | # sleep
108 |
109 | t_sleep = update_interval - (time.time() - t_start)
110 |
111 | if t_sleep < 0:
112 | logging.info('Update took longer time than sleep interval, skipping sleep')
113 | else:
114 | logging.info('Sleeping for %i seconds' % t_sleep)
115 | time.sleep(t_sleep)
116 | logging.info('--')
117 |
118 |
119 | if __name__ == '__main__':
120 | main()
121 |
122 |
--------------------------------------------------------------------------------