Add support for unified Bird daemons

Bird 2.0 includes IPv4 and IPv6 support in a single daemon.
When UNIFIED_DAEMON is set to True, queries are always done with the
"ipv4" backend (which handles both protocols), and distinctions between
IPv4 and IPv4 are removed in the UI.
This commit is contained in:
Zhaofeng Li 2018-11-28 10:49:44 -08:00 committed by Simon Marsh
parent daaf981b32
commit ddf86d02fb
5 changed files with 71 additions and 30 deletions

4
lg.cfg

@ -13,6 +13,10 @@ PROXY = {
"h3": "h3.some.network:5000",
}
# If True, queries are always done with the "ipv4" backend,
# and the distinction between IPv4 and IPv6 is removed from the UI.
UNIFIED_DAEMON = True
# Used for bgpmap
ROUTER_IP = {
"gw" : [ "91.224.148.2", "2a01:6600:8000::175" ],

26
lg.py

@ -32,7 +32,7 @@ from urllib import quote, unquote
import json
import random
from toolbox import mask_is_valid, ipv6_is_valid, ipv4_is_valid, resolve, save_cache_pickle, load_cache_pickle, unescape
from toolbox import mask_is_valid, ip_is_valid, ipv6_is_valid, ipv4_is_valid, resolve, resolve_any, save_cache_pickle, load_cache_pickle, unescape
#from xml.sax.saxutils import escape
@ -119,6 +119,9 @@ def whois_command(query):
def bird_command(host, proto, query):
"""Alias to bird_proxy for bird service"""
if app.config.get("UNIFIED_DAEMON", False):
return bird_proxy(host, "ipv4", "bird", query)
else:
return bird_proxy(host, proto, "bird", query)
@ -305,6 +308,13 @@ def traceroute(hosts, proto):
set_session("traceroute", hosts, proto, q)
if app.config.get("UNIFIED_DAEMON", False):
if not ip_is_valid(q):
try:
q = resolve_any(q)
except:
return error_page("%s is unresolvable" % q)
else:
if proto == "ipv6" and not ipv6_is_valid(q):
try:
q = resolve(q, "AAAA")
@ -608,6 +618,20 @@ def show_route(request_type, hosts, proto):
if len(expression.split("/")) == 2:
expression, mask = (expression.split("/"))
if app.config.get("UNIFIED_DAEMON", False):
if not ip_is_valid(expression):
try:
expression = resolve_any(expression)
except:
return error_page("%s is unresolvable" % expression)
if not mask and ipv4_is_valid(expression):
mask = "32"
if not mask and ipv6_is_valid(expression):
mask = "128"
if not mask_is_valid(mask):
return error_page("mask %s is invalid" % mask)
else:
if not mask and proto == "ipv4":
mask = "32"
if not mask and proto == "ipv6":

@ -1,7 +1,7 @@
{% extends "layout.html" %}
{% block body %}
{% for host in detail %}
<h3>{{host}}/{{session.proto}}: {{command}}</h3>
<h3>{{host}}{% if not config.UNIFIED_DAEMON %}/{{session.proto}}{% endif %}: {{command}}</h3>
<i>{{ detail[host].status }}</i><br /><br />
<pre>
{{ detail[host].description|trim|safe }}

@ -24,10 +24,12 @@
{% endfor %}
</ul>
{% if not config.UNIFIED_DAEMON %}
<div class="btn-group">
<a class="btn btn-primary proto" id="ipv4" href="#">ipv4</a>
<a class="btn btn-primary proto" id="ipv6" href="#">ipv6</a>
</div>
{% endif %}
<ul class="nav">
<li class="nav-item dropdown request_type">
@ -74,7 +76,7 @@
{% for hosts, proto, request_type, request_args in session.history %}
<a class="list-group-item list-group-item-action {% if loop.first %}active{% endif %}"
href="/{{ [request_type, hosts, proto]|join("/") }}{% if request_args %}?q={{request_args}}{% endif %}">
{{hosts}}/{{proto}}: {{ commands_dict[request_type]|replace("...", request_args) }}
{{hosts}}{% if not config.UNIFIED_DAEMON %}/{{proto}}{% endif %}: {{ commands_dict[request_type]|replace("...", request_args) }}
</a>
{% endfor %}

@ -31,6 +31,14 @@ resolv.lifetime = 1
def resolve(n, q):
return str(resolv.query(n,q)[0])
def resolve_any(h):
try:
return resolve(h, "AAAA")
except:
pass
return resolve(h, "A")
def mask_is_valid(n):
if not n:
return True
@ -40,6 +48,9 @@ def mask_is_valid(n):
except:
return False
def ip_is_valid(n):
return ipv4_is_valid(n) or ipv6_is_valid(n)
def ipv4_is_valid(n):
try:
socket.inet_pton(socket.AF_INET, n)