bird-lg/lg.py

212 lines
5.7 KiB
Python
Raw Normal View History

2011-12-16 11:02:24 +01:00
#!/usr/bin/python
2012-01-16 14:13:49 +01:00
import sys, os, subprocess, re
2011-12-16 13:19:48 +01:00
from dns import resolver,reversename
2012-01-16 14:13:49 +01:00
from flask import Flask, render_template, jsonify, redirect
2011-12-16 11:02:24 +01:00
app = Flask(__name__)
import socket
2011-12-16 13:19:48 +01:00
def get_ip(n, q):
return str(resolver.query(n,q)[0])
2011-12-16 11:02:24 +01:00
def check_mask(n):
if not n:
return True
try:
mask = int(n)
return ( mask > 1 and mask < 128)
except:
return False
def check_ipv4(n):
try:
socket.inet_pton(socket.AF_INET, n)
return True
except socket.error:
return False
def check_ipv6(n):
try:
socket.inet_pton(socket.AF_INET6, n)
return True
except socket.error:
return False
2012-01-16 14:13:49 +01:00
def cleanup_output(text):
return "\n".join([ add_link(re.sub(r'^[0-9]*-', r' ', line)) for line in text.split("\n") if not line.startswith("0000") ])
def add_link(text):
if text.strip().startswith("BGP.as_path:") or \
text.strip().startswith("Neighbor AS:") :
return re.sub(r'([0-9]*)',r'<a href="/whois/\1">\1</a>',text)
else:
return text
#@app.errorhandler(404)
#def notfound(error):
# return redirect("/")
2011-12-16 11:02:24 +01:00
@app.route("/")
def hello():
return render_template('index.html')
2012-01-16 14:13:49 +01:00
@app.route("/whois/<asnum>")
def whois(asnum):
output = "<h3> Whois as" + asnum + "</h3><pre>"
try:
asnum = int(asnum)
except:
output += "Failed to parse as%s"%asnum
else:
output += subprocess.Popen(['whois', 'as%d'%asnum], stdout=subprocess.PIPE).communicate()[0].decode('utf-8', 'ignore')
output += "</pre>"
return render_template('index.html', output=output, typ="whois", asnum=asnum)
@app.route("/prefix_detail/<host>/<proto>/")
@app.route("/prefix_detail/<host>/<proto>/<prefix>")
@app.route("/prefix_detail/<host>/<proto>/<prefix>/<mask>")
def show_route_for_prefix_detail(host, proto, prefix="", mask=""):
return show_route_for_prefix(host, proto=proto, prefix=prefix, mask=mask, all = True)
@app.route("/prefix/<host>/<proto>/")
@app.route("/prefix/<host>/<proto>/<prefix>")
@app.route("/prefix/<host>/<proto>/<prefix>/<mask>")
def show_route_for_prefix(host, proto, prefix="", mask="", all=False):
2011-12-16 13:19:48 +01:00
qprefix = prefix
2011-12-16 11:02:24 +01:00
2011-12-16 19:05:16 +01:00
2011-12-16 11:02:24 +01:00
# security check
2011-12-16 13:19:48 +01:00
allowed = True
2011-12-16 19:05:16 +01:00
if not prefix:
allowed = False
elif not check_mask(mask):
2011-12-16 13:19:48 +01:00
allowed = False
elif proto == "ipv6":
if not check_ipv6(prefix):
try:
qprefix = get_ip(prefix, "AAAA")
except:
qprefix = "unresolvable"
2011-12-16 13:19:48 +01:00
allowed = False
2011-12-16 13:19:48 +01:00
elif proto == "ipv4":
if not check_ipv4(prefix):
try:
qprefix = get_ip(prefix, "A")
except:
qprefix = "unresolvable"
2011-12-16 13:19:48 +01:00
allowed = False
else:
allowed = False
2011-12-16 19:05:16 +01:00
2011-12-18 12:32:00 +01:00
output = '<h3>' + host + ' (' + proto + ') show route for ' + prefix + (prefix != qprefix and " (%s)"%qprefix or "") + (mask and '/' + mask or '' ) + (all and " all" or "") + '</h3>'
2012-01-16 14:13:49 +01:00
2011-12-16 13:19:48 +01:00
if allowed:
if mask: qprefix = qprefix +"/"+mask
2011-12-16 11:02:24 +01:00
if mask: prefix = prefix +"/"+mask
2012-01-16 14:13:49 +01:00
ok, string = get_cmd_result(host , proto, "show route for " + qprefix + (all and " all" or ""))
2011-12-16 11:02:24 +01:00
if ok:
2012-01-16 14:13:49 +01:00
output += '<pre>' + cleanup_output(string) + '</pre>'
2011-12-16 11:02:24 +01:00
else:
output += string
else:
if prefix and qprefix != "unresolvable":
output += prefix + ' not valid'
elif prefix:
output += prefix + ' unresolvable'
2011-12-16 19:05:16 +01:00
else:
output += 'prefix missing'
2011-12-16 13:19:48 +01:00
2011-12-18 12:32:00 +01:00
return render_template('index.html', output=output, typ="prefix" + (all and "_detail" or ""), host=host+"/"+proto, prefix=prefix)
2011-12-16 11:02:24 +01:00
2012-01-16 14:13:49 +01:00
@app.route("/detail/<host>/<proto>/")
@app.route("/detail/<host>/<proto>/<name>")
2011-12-16 19:05:16 +01:00
def detail(host, proto, name=""):
output = '<h3>' + host + ' (' + proto + ') show protocols all ' + name + '</h3>'
2011-12-16 11:02:24 +01:00
2012-01-16 14:13:49 +01:00
if not name:
output += "name missing"
else:
2011-12-16 19:05:16 +01:00
ok, string = get_cmd_result(host , proto, "show protocols all " + name)
if ok:
2012-01-16 14:13:49 +01:00
output += '<pre>'
output += "\n".join([ add_link(s.strip()) for s in string.split("\n") if s.startswith(" ")])
output += '</pre>'
2011-12-16 19:05:16 +01:00
else:
output += string
2011-12-16 11:02:24 +01:00
return render_template('index.html', output=output, typ="detail", host=host+"/"+proto, name=name)
2012-01-16 14:13:49 +01:00
@app.route("/summary/<host>")
@app.route("/summary/<host>/<proto>")
2011-12-16 19:05:16 +01:00
def summary(host, proto="ipv4"):
output = '<h3>' + host + ' (' + proto + ') show protocols</h3>'
2011-12-16 11:02:24 +01:00
ok, string = get_cmd_result(host , proto, "show protocols")
if ok:
output += '<pre><table>'
2011-12-16 12:52:56 +01:00
for infos in string.split("\n"):
if not infos.startswith(" "): continue
2011-12-16 11:02:24 +01:00
d = infos.split()
name = d[0]
typ = d[1]
if typ == "BGP":
2012-01-16 14:13:49 +01:00
output += '<tr><td><a href="/detail/%s/%s/%s">%s</a><td><td>%s</td></tr>'%(host,proto,name,name,infos.replace(name,"").strip())
2011-12-16 11:02:24 +01:00
output += '</table></pre>'
else:
output += string
return render_template('index.html', output=output, typ="summary", host=host+"/"+proto)
@app.route("/<host>/<proto>/status")
def status(host, proto):
string = get_cmd_result(host, proto, "show status")
output = '<pre>' + string + '</pre>'
return render_template('index.html', output=output, host=host+"/"+proto)
def get_cmd_result(host, proto, cmd):
ret = True
if proto == "ipv4":
port = 9994
else:
port = 9996
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(3.0)
# sock.setblocking(0)
try:
sock.connect((host, port))
app.logger.debug("open socket on %s:%d", host, port)
2011-12-16 11:02:24 +01:00
sock.send(cmd + "\n")
app.logger.debug("send %s socket on %s:%d", cmd, host, port)
2011-12-16 11:02:24 +01:00
bufsize = 4096
data = sock.recv(bufsize)
string = data
app.logger.debug("read %s (%d)", data, len(data))
2011-12-16 11:02:24 +01:00
code = string.split("\n")[-2][0:4]
2011-12-16 12:52:56 +01:00
while not code[0] in ["0", "9", "8"]:
2011-12-16 11:02:24 +01:00
data = sock.recv(bufsize)
string = string + data
app.logger.debug("read %s (%d)", data, len(data))
2011-12-16 11:02:24 +01:00
code = string.strip()[len(string.strip())-4:]
2011-12-16 12:52:56 +01:00
if code[0] in [ "9", "8" ]:
2011-12-16 11:02:24 +01:00
ret = False
app.logger.debug("return %s",string)
2011-12-16 11:02:24 +01:00
except Exception as detail:
ret = False
string = "Failed connect to %s:%d (%s)"%(host, port, detail)
app.logger.error(string)
sock.close()
return (ret, string)
2012-01-16 14:13:49 +01:00
app.debug = True
2011-12-16 11:02:24 +01:00
if __name__ == "__main__":
2012-01-16 14:13:49 +01:00
app.run("0.0.0.0")