mirror of
https://github.com/sileht/bird-lg.git
synced 2024-11-22 06:54:43 +01:00
Add BGPmaps
This commit is contained in:
parent
eb4f4f52b3
commit
2a15a0cfc3
72
lg.py
72
lg.py
|
@ -24,10 +24,12 @@ import subprocess
|
|||
import re
|
||||
from urllib2 import urlopen
|
||||
from urllib import quote, unquote
|
||||
import json
|
||||
|
||||
from toolbox import mask_is_valid, ipv6_is_valid, ipv4_is_valid, resolve
|
||||
|
||||
from flask import Flask, render_template, jsonify, redirect, session, request, abort
|
||||
import pydot
|
||||
from flask import Flask, render_template, jsonify, redirect, session, request, abort, Response
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.from_pyfile('lg.cfg')
|
||||
|
@ -54,6 +56,15 @@ def add_links(text):
|
|||
ret_text.append(line)
|
||||
return "\n".join(ret_text)
|
||||
|
||||
def extract_paths(text):
|
||||
paths = []
|
||||
for line in text:
|
||||
line = line.strip()
|
||||
if line.startswith("BGP.as_path:"):
|
||||
paths.append(line.replace("BGP.as_path:", "").strip().split(" "))
|
||||
|
||||
return paths
|
||||
|
||||
def set_session(request_type, hosts, proto, request_args):
|
||||
""" Store all data from user in the user session """
|
||||
session.permanent = True
|
||||
|
@ -74,6 +85,9 @@ def set_session(request_type, hosts, proto, request_args):
|
|||
history.insert(0, t)
|
||||
session["history"] = history[:20]
|
||||
|
||||
def whois_command(query):
|
||||
return subprocess.Popen( [ 'whois', query], stdout=subprocess.PIPE).communicate()[0].decode('utf-8', 'ignore')
|
||||
|
||||
def bird_command(host, proto, query):
|
||||
"""Alias to bird_proxy for bird service"""
|
||||
return bird_proxy(host, proto, "bird", query)
|
||||
|
@ -150,7 +164,7 @@ def whois(query):
|
|||
except:
|
||||
m = re.match(r"[\w\d-]*\.(?P<domain>[\d\w-]+\.[\d\w-]+)$", query)
|
||||
if m: query = query.groupdict()["domain"]
|
||||
output = subprocess.Popen( [ 'whois', query], stdout=subprocess.PIPE).communicate()[0].decode('utf-8', 'ignore').replace("\n","<br>")
|
||||
output = whois_command(query).replace("\n","<br>")
|
||||
return jsonify(output=output, title=query)
|
||||
|
||||
SUMMARY_UNWANTED_PROTOS = ["Kernel", "Static", "Device"]
|
||||
|
@ -243,6 +257,56 @@ def show_route_for(hosts, proto):
|
|||
def show_route_for_detail(hosts, proto):
|
||||
return show_route("prefix_detail", hosts, proto)
|
||||
|
||||
ASNAME_CACHE = {}
|
||||
def get_as_name(_as):
|
||||
if True or not ASNAME_CACHE.has_key(_as):
|
||||
whois_answer = whois_command("as%s" % _as)
|
||||
as_name = re.search('as-name: (.*)', whois_answer)
|
||||
if as_name:
|
||||
ASNAME_CACHE[_as] = as_name.group(1).strip()
|
||||
else:
|
||||
ASNAME_CACHE[_as] = _as
|
||||
if ASNAME_CACHE[_as] == _as:
|
||||
return "AS%s" % _as
|
||||
else:
|
||||
return "AS%s\r%s" % (_as, ASNAME_CACHE[_as])
|
||||
|
||||
@app.route("/bgpmap/<data>")
|
||||
def show_bgpmap(data):
|
||||
data = json.loads(unquote(data))
|
||||
graph = pydot.Dot('BGPMAP', graph_type='digraph')
|
||||
nodes = {}
|
||||
edges = {}
|
||||
for host, asmaps in data.iteritems():
|
||||
nodes[host] = pydot.Node(host, shape="box", style="filled", fillcolor="#F5A9A9")
|
||||
graph.add_node(nodes[host])
|
||||
for host, asmaps in data.iteritems():
|
||||
first = True
|
||||
for asmap in asmaps:
|
||||
previous_as = host
|
||||
for _as in asmap:
|
||||
_as = get_as_name(_as)
|
||||
if _as == previous_as:
|
||||
continue
|
||||
if not nodes.has_key(_as):
|
||||
nodes[_as] = pydot.Node(_as, style="filled", fillcolor=(first and "#F5A9A9" or "white"))
|
||||
graph.add_node(nodes[_as])
|
||||
|
||||
edge_tuple = (nodes[previous_as], nodes[_as])
|
||||
if not edges.has_key(edge_tuple):
|
||||
edge = pydot.Edge(*edge_tuple)
|
||||
graph.add_edge(edge)
|
||||
edges[edge_tuple] = edge
|
||||
|
||||
if edge.get_color() != "red" and first:
|
||||
edge.set_color("red")
|
||||
|
||||
previous_as = _as
|
||||
first = False
|
||||
|
||||
#return Response("<pre>" + graph.create_dot() + "</pre>")
|
||||
return Response(graph.create_png(), mimetype='image/png')
|
||||
|
||||
def show_route(request_type, hosts, proto):
|
||||
expression = unquote(request.args.get('q', ''))
|
||||
if not expression.strip(): abort(400)
|
||||
|
@ -275,16 +339,18 @@ def show_route(request_type, hosts, proto):
|
|||
|
||||
detail = {}
|
||||
error = []
|
||||
bgpmap = {}
|
||||
for host in hosts.split("+"):
|
||||
ret, res = bird_command(host, proto, command)
|
||||
|
||||
res = res.split("\n")
|
||||
if len(res) > 1 : #if ret:
|
||||
detail[host] = add_links(res)
|
||||
bgpmap[host] = extract_paths(res)
|
||||
else:
|
||||
error.append("%s: bird command failed with error, %s" % (host,"\n".join(res)))
|
||||
|
||||
return render_template('route.html', detail=detail, command=command, expression=expression, error="<br>".join(error) )
|
||||
return render_template('route.html', detail=detail, command=command, expression=expression, bgpmap=json.dumps(bgpmap), error="<br>".join(error) )
|
||||
|
||||
app.secret_key = app.config["SESSION_KEY"]
|
||||
app.debug = True
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
<pre>
|
||||
{{ detail[host]|trim|safe }}
|
||||
</pre>
|
||||
<br />
|
||||
{% endfor %}
|
||||
<a href="/bgpmap/{{bgpmap}}"><img src="/bgpmap/{{bgpmap}}" /></a>
|
||||
<br />
|
||||
{% endblock %}
|
||||
|
|
Loading…
Reference in a new issue