mirror of
https://github.com/xddxdd/bird-lg-go
synced 2024-11-27 08:53:38 +01:00
General code cleanup
This commit is contained in:
parent
0c06a85a93
commit
8f581d378f
19
.gitignore
vendored
Normal file
19
.gitignore
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
.DS_Store
|
||||
frontend/frontend
|
||||
proxy/proxy
|
@ -1,20 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func birdRouteToGraphviz(servers []string, responses []string, target string) string {
|
||||
var edges string
|
||||
edges += "\"Target: " + target + "\" [color=red,shape=diamond];\n"
|
||||
graph := make(map[string]string)
|
||||
// Helper to add an edge
|
||||
addEdge := func(src string, dest string, attr string) {
|
||||
key := "\"" + src + "\" -> \"" + dest + "\""
|
||||
_, present := graph[key]
|
||||
// Do not remove edge's attributes if it's already present
|
||||
if present && len(attr) == 0 {
|
||||
return
|
||||
}
|
||||
graph[key] = attr
|
||||
}
|
||||
// Helper to set attribute for a point in graph
|
||||
addPoint := func(name string, attr string) {
|
||||
key := "\"" + name + "\""
|
||||
_, present := graph[key]
|
||||
// Do not remove point's attributes if it's already present
|
||||
if present && len(attr) == 0 {
|
||||
return
|
||||
}
|
||||
graph[key] = attr
|
||||
}
|
||||
|
||||
addPoint("Target: "+target, "[color=red,shape=diamond]")
|
||||
for serverID, server := range servers {
|
||||
response := responses[serverID]
|
||||
if len(response) == 0 {
|
||||
continue
|
||||
}
|
||||
edges += "\"" + server + "\" [color=blue,shape=box];\n"
|
||||
addPoint(server, "[color=blue,shape=box]")
|
||||
// This is the best split point I can find for bird2
|
||||
routes := strings.Split(response, "\tvia ")
|
||||
routeFound := false
|
||||
for routeIndex, route := range routes {
|
||||
var routeNexthop string
|
||||
var routeASPath string
|
||||
@ -28,7 +50,8 @@ func birdRouteToGraphviz(servers []string, responses []string, target string) st
|
||||
routeASPath = strings.TrimPrefix(routeParameter, "\tBGP.as_path: ")
|
||||
}
|
||||
}
|
||||
if len(routeNexthop) == 0 || len(routeASPath) == 0 {
|
||||
if len(routeASPath) == 0 {
|
||||
// Either this is not a BGP route, or the information is incomplete
|
||||
continue
|
||||
}
|
||||
|
||||
@ -39,13 +62,15 @@ func birdRouteToGraphviz(servers []string, responses []string, target string) st
|
||||
if len(paths) > 0 {
|
||||
if len(routeNexthop) > 0 {
|
||||
// Edge from originating server to nexthop
|
||||
edges += "\"" + server + "\" -> \"Nexthop:\\n" + routeNexthop + "\"" + (map[bool]string{true: " [color=red]"})[routePreferred] + ";\n"
|
||||
addEdge(server, "Nexthop:\\n"+routeNexthop, (map[bool]string{true: "[color=red]"})[routePreferred])
|
||||
// and from nexthop to AS
|
||||
edges += "\"Nexthop:\\n" + routeNexthop + "\" -> \"AS" + paths[0] + "\"" + (map[bool]string{true: " [color=red]"})[routePreferred] + ";\n"
|
||||
edges += "\"Nexthop:\\n" + routeNexthop + "\" [shape=diamond];\n"
|
||||
addEdge("Nexthop:\\n"+routeNexthop, "AS"+paths[0], (map[bool]string{true: "[color=red]"})[routePreferred])
|
||||
addPoint("Nexthop:\\n"+routeNexthop, "[shape=diamond]")
|
||||
routeFound = true
|
||||
} else {
|
||||
// Edge from originating server to AS
|
||||
edges += "\"" + server + "\" -> \"AS" + paths[0] + "\"" + (map[bool]string{true: " [color=red]"})[routePreferred] + ";\n"
|
||||
addEdge(server, "AS"+paths[0], (map[bool]string{true: "[color=red]"})[routePreferred])
|
||||
routeFound = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,25 +79,22 @@ func birdRouteToGraphviz(servers []string, responses []string, target string) st
|
||||
if pathIndex == 0 {
|
||||
continue
|
||||
}
|
||||
edges += "\"AS" + paths[pathIndex-1] + "\" -> \"AS" + paths[pathIndex] + "\"" + (map[bool]string{true: " [color=red]"})[routePreferred] + ";\n"
|
||||
addEdge("AS"+paths[pathIndex-1], "AS"+paths[pathIndex], (map[bool]string{true: "[color=red]"})[routePreferred])
|
||||
}
|
||||
// Last AS to destination
|
||||
edges += "\"AS" + paths[len(paths)-1] + "\" -> \"Target: " + target + "\"" + (map[bool]string{true: " [color=red]"})[routePreferred] + ";\n"
|
||||
addEdge("AS"+paths[len(paths)-1], "Target: "+target, (map[bool]string{true: "[color=red]"})[routePreferred])
|
||||
}
|
||||
if !strings.Contains(edges, "\""+server+"\" ->") {
|
||||
// Cannot get path information from bird
|
||||
edges += "\"" + server + "\" -> \"Target: " + target + "\" [color=gray,label=\"?\"]"
|
||||
}
|
||||
}
|
||||
// Deduplication of edges: sort, then remove if current entry is prefix of next entry
|
||||
var result string
|
||||
edgesSorted := strings.Split(edges, ";\n")
|
||||
sort.Strings(edgesSorted)
|
||||
for edgeIndex, edge := range edgesSorted {
|
||||
if edgeIndex >= len(edgesSorted)-1 || !strings.HasPrefix(edgesSorted[edgeIndex+1], edge) {
|
||||
result += edge + ";\n"
|
||||
|
||||
if !routeFound {
|
||||
// Cannot find a path starting from this server
|
||||
addEdge(server, "Target: "+target, "[color=gray,label=\"?\"?]")
|
||||
}
|
||||
}
|
||||
|
||||
// Combine all graphviz commands
|
||||
var result string
|
||||
for edge, attr := range graph {
|
||||
result += edge + " " + attr + ";\n"
|
||||
}
|
||||
return "digraph {\n" + result + "}\n"
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html"
|
||||
"net/http"
|
||||
"strings"
|
||||
@ -17,65 +18,91 @@ func webHandlerWhois(w http.ResponseWriter, r *http.Request) {
|
||||
templateFooter(w)
|
||||
}
|
||||
|
||||
func webBackendCommunicator(w http.ResponseWriter, r *http.Request, endpoint string, command string) {
|
||||
split := strings.Split(r.URL.Path[1:], "/")
|
||||
urlCommands := strings.Join(split[3:], "/")
|
||||
|
||||
command = (map[string]string{
|
||||
func webBackendCommunicator(endpoint string, command string) func(w http.ResponseWriter, r *http.Request) {
|
||||
backendCommandPrimitive, commandPresent := (map[string]string{
|
||||
"summary": "show protocols",
|
||||
"detail": "show protocols all " + urlCommands,
|
||||
"route": "show route for " + urlCommands,
|
||||
"route_all": "show route for " + urlCommands + " all",
|
||||
"route_where": "show route where net ~ [ " + urlCommands + " ]",
|
||||
"route_where_all": "show route where net ~ [ " + urlCommands + " ] all",
|
||||
"traceroute": urlCommands,
|
||||
"detail": "show protocols all %s",
|
||||
"route": "show route for %s",
|
||||
"route_all": "show route for %s all",
|
||||
"route_where": "show route where net ~ [ %s ]",
|
||||
"route_where_all": "show route where net ~ [ %s ] all",
|
||||
"traceroute": "%s",
|
||||
})[command]
|
||||
|
||||
templateHeader(w, r, "Bird-lg Go - "+html.EscapeString(endpoint+" "+command))
|
||||
|
||||
var servers []string = strings.Split(split[2], "+")
|
||||
|
||||
var responses []string = batchRequest(servers, endpoint, command)
|
||||
for i, response := range responses {
|
||||
w.Write([]byte("<h2>" + html.EscapeString(servers[i]) + ": " + html.EscapeString(command) + "</h2>"))
|
||||
if (endpoint == "bird" || endpoint == "bird6") && command == "show protocols" && len(response) > 4 && strings.ToLower(response[0:4]) == "name" {
|
||||
var isIPv6 bool = endpoint[len(endpoint)-1] == '6'
|
||||
summaryTable(w, isIPv6, response, servers[i])
|
||||
} else {
|
||||
smartWriter(w, response)
|
||||
}
|
||||
if !commandPresent {
|
||||
panic("invalid command: " + command)
|
||||
}
|
||||
|
||||
templateFooter(w)
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
split := strings.Split(r.URL.Path[1:], "/")
|
||||
urlCommands := strings.Join(split[3:], "/")
|
||||
|
||||
var backendCommand string
|
||||
if strings.Contains(backendCommandPrimitive, "%") {
|
||||
backendCommand = fmt.Sprintf(backendCommandPrimitive, urlCommands)
|
||||
} else {
|
||||
backendCommand = backendCommandPrimitive
|
||||
}
|
||||
|
||||
templateHeader(w, r, "Bird-lg Go - "+html.EscapeString(endpoint+" "+backendCommand))
|
||||
|
||||
var servers []string = strings.Split(split[2], "+")
|
||||
|
||||
var responses []string = batchRequest(servers, endpoint, backendCommand)
|
||||
for i, response := range responses {
|
||||
w.Write([]byte("<h2>" + html.EscapeString(servers[i]) + ": " + html.EscapeString(backendCommand) + "</h2>"))
|
||||
if (endpoint == "bird" || endpoint == "bird6") && backendCommand == "show protocols" && len(response) > 4 && strings.ToLower(response[0:4]) == "name" {
|
||||
var isIPv6 bool = endpoint[len(endpoint)-1] == '6'
|
||||
summaryTable(w, isIPv6, response, servers[i])
|
||||
} else {
|
||||
smartWriter(w, response)
|
||||
}
|
||||
}
|
||||
|
||||
templateFooter(w)
|
||||
}
|
||||
}
|
||||
|
||||
func webHandlerBGPMap(w http.ResponseWriter, r *http.Request, endpoint string, command string) {
|
||||
split := strings.Split(r.URL.Path[1:], "/")
|
||||
urlCommands := strings.Join(split[3:], "/")
|
||||
|
||||
command = (map[string]string{
|
||||
"route_bgpmap": "show route for " + urlCommands + " all",
|
||||
"route_where_bgpmap": "show route where net ~ [ " + urlCommands + " ] all",
|
||||
func webHandlerBGPMap(endpoint string, command string) func(w http.ResponseWriter, r *http.Request) {
|
||||
backendCommandPrimitive, commandPresent := (map[string]string{
|
||||
"route_bgpmap": "show route for %s all",
|
||||
"route_where_bgpmap": "show route where net ~ [ %s ] all",
|
||||
})[command]
|
||||
|
||||
templateHeader(w, r, "Bird-lg Go - "+html.EscapeString(endpoint+" "+command))
|
||||
if !commandPresent {
|
||||
panic("invalid command: " + command)
|
||||
}
|
||||
|
||||
var servers []string = strings.Split(split[2], "+")
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
split := strings.Split(r.URL.Path[1:], "/")
|
||||
urlCommands := strings.Join(split[3:], "/")
|
||||
|
||||
var responses []string = batchRequest(servers, endpoint, command)
|
||||
w.Write([]byte(`
|
||||
<script>
|
||||
var viz = new Viz();
|
||||
viz.renderSVGElement(` + "`" + birdRouteToGraphviz(servers, responses, urlCommands) + "`" + `)
|
||||
.then(function(element) {
|
||||
document.body.appendChild(element);
|
||||
})
|
||||
.catch(error => {
|
||||
document.body.appendChild("<pre>"+error+"</pre>")
|
||||
});
|
||||
</script>`))
|
||||
var backendCommand string
|
||||
if strings.Contains(backendCommandPrimitive, "%") {
|
||||
backendCommand = fmt.Sprintf(backendCommandPrimitive, urlCommands)
|
||||
} else {
|
||||
backendCommand = backendCommandPrimitive
|
||||
}
|
||||
|
||||
templateFooter(w)
|
||||
templateHeader(w, r, "Bird-lg Go - "+html.EscapeString(endpoint+" "+backendCommand))
|
||||
|
||||
var servers []string = strings.Split(split[2], "+")
|
||||
|
||||
var responses []string = batchRequest(servers, endpoint, backendCommand)
|
||||
w.Write([]byte(`
|
||||
<script>
|
||||
var viz = new Viz();
|
||||
viz.renderSVGElement(` + "`" + birdRouteToGraphviz(servers, responses, urlCommands) + "`" + `)
|
||||
.then(function(element) {
|
||||
document.body.appendChild(element);
|
||||
})
|
||||
.catch(error => {
|
||||
document.body.appendChild("<pre>"+error+"</pre>")
|
||||
});
|
||||
</script>`))
|
||||
|
||||
templateFooter(w)
|
||||
}
|
||||
}
|
||||
|
||||
func webHandlerNavbarFormRedirect(w http.ResponseWriter, r *http.Request) {
|
||||
@ -94,26 +121,24 @@ func webServerStart() {
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, "/ipv4/summary/"+strings.Join(settingServers[:], "+"), 302)
|
||||
})
|
||||
http.HandleFunc("/ipv4/summary/", func(w http.ResponseWriter, r *http.Request) { webBackendCommunicator(w, r, "bird", "summary") })
|
||||
http.HandleFunc("/ipv6/summary/", func(w http.ResponseWriter, r *http.Request) { webBackendCommunicator(w, r, "bird6", "summary") })
|
||||
http.HandleFunc("/ipv4/detail/", func(w http.ResponseWriter, r *http.Request) { webBackendCommunicator(w, r, "bird", "detail") })
|
||||
http.HandleFunc("/ipv6/detail/", func(w http.ResponseWriter, r *http.Request) { webBackendCommunicator(w, r, "bird6", "detail") })
|
||||
http.HandleFunc("/ipv4/route/", func(w http.ResponseWriter, r *http.Request) { webBackendCommunicator(w, r, "bird", "route") })
|
||||
http.HandleFunc("/ipv6/route/", func(w http.ResponseWriter, r *http.Request) { webBackendCommunicator(w, r, "bird6", "route") })
|
||||
http.HandleFunc("/ipv4/route_all/", func(w http.ResponseWriter, r *http.Request) { webBackendCommunicator(w, r, "bird", "route_all") })
|
||||
http.HandleFunc("/ipv6/route_all/", func(w http.ResponseWriter, r *http.Request) { webBackendCommunicator(w, r, "bird6", "route_all") })
|
||||
http.HandleFunc("/ipv4/route_bgpmap/", func(w http.ResponseWriter, r *http.Request) { webHandlerBGPMap(w, r, "bird", "route_bgpmap") })
|
||||
http.HandleFunc("/ipv6/route_bgpmap/", func(w http.ResponseWriter, r *http.Request) { webHandlerBGPMap(w, r, "bird6", "route_bgpmap") })
|
||||
http.HandleFunc("/ipv4/route_where/", func(w http.ResponseWriter, r *http.Request) { webBackendCommunicator(w, r, "bird", "route_where") })
|
||||
http.HandleFunc("/ipv6/route_where/", func(w http.ResponseWriter, r *http.Request) { webBackendCommunicator(w, r, "bird6", "route_where") })
|
||||
http.HandleFunc("/ipv4/route_where_all/", func(w http.ResponseWriter, r *http.Request) { webBackendCommunicator(w, r, "bird", "route_where_all") })
|
||||
http.HandleFunc("/ipv6/route_where_all/", func(w http.ResponseWriter, r *http.Request) { webBackendCommunicator(w, r, "bird6", "route_where_all") })
|
||||
http.HandleFunc("/ipv4/route_where_bgpmap/", func(w http.ResponseWriter, r *http.Request) { webHandlerBGPMap(w, r, "bird", "route_where_bgpmap") })
|
||||
http.HandleFunc("/ipv6/route_where_bgpmap/", func(w http.ResponseWriter, r *http.Request) { webHandlerBGPMap(w, r, "bird6", "route_where_bgpmap") })
|
||||
http.HandleFunc("/ipv4/traceroute/", func(w http.ResponseWriter, r *http.Request) { webBackendCommunicator(w, r, "traceroute", "traceroute") })
|
||||
http.HandleFunc("/ipv6/traceroute/", func(w http.ResponseWriter, r *http.Request) {
|
||||
webBackendCommunicator(w, r, "traceroute6", "traceroute")
|
||||
})
|
||||
http.HandleFunc("/ipv4/summary/", webBackendCommunicator("bird", "summary"))
|
||||
http.HandleFunc("/ipv6/summary/", webBackendCommunicator("bird6", "summary"))
|
||||
http.HandleFunc("/ipv4/detail/", webBackendCommunicator("bird", "detail"))
|
||||
http.HandleFunc("/ipv6/detail/", webBackendCommunicator("bird6", "detail"))
|
||||
http.HandleFunc("/ipv4/route/", webBackendCommunicator("bird", "route"))
|
||||
http.HandleFunc("/ipv6/route/", webBackendCommunicator("bird6", "route"))
|
||||
http.HandleFunc("/ipv4/route_all/", webBackendCommunicator("bird", "route_all"))
|
||||
http.HandleFunc("/ipv6/route_all/", webBackendCommunicator("bird6", "route_all"))
|
||||
http.HandleFunc("/ipv4/route_bgpmap/", webHandlerBGPMap("bird", "route_bgpmap"))
|
||||
http.HandleFunc("/ipv6/route_bgpmap/", webHandlerBGPMap("bird6", "route_bgpmap"))
|
||||
http.HandleFunc("/ipv4/route_where/", webBackendCommunicator("bird", "route_where"))
|
||||
http.HandleFunc("/ipv6/route_where/", webBackendCommunicator("bird6", "route_where"))
|
||||
http.HandleFunc("/ipv4/route_where_all/", webBackendCommunicator("bird", "route_where_all"))
|
||||
http.HandleFunc("/ipv6/route_where_all/", webBackendCommunicator("bird6", "route_where_all"))
|
||||
http.HandleFunc("/ipv4/route_where_bgpmap/", webHandlerBGPMap("bird", "route_where_bgpmap"))
|
||||
http.HandleFunc("/ipv6/route_where_bgpmap/", webHandlerBGPMap("bird6", "route_where_bgpmap"))
|
||||
http.HandleFunc("/ipv4/traceroute/", webBackendCommunicator("traceroute", "traceroute"))
|
||||
http.HandleFunc("/ipv6/traceroute/", webBackendCommunicator("traceroute6", "traceroute"))
|
||||
http.HandleFunc("/whois/", webHandlerWhois)
|
||||
http.HandleFunc("/redir/", webHandlerNavbarFormRedirect)
|
||||
http.ListenAndServe(settingListen, nil)
|
||||
|
Loading…
Reference in New Issue
Block a user