mirror of
https://github.com/maride/pancap.git
synced 2024-10-18 12:06:32 +00:00
105 lines
2.3 KiB
Go
105 lines
2.3 KiB
Go
package output
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
|
|
"crypto/sha256"
|
|
|
|
"github.com/google/gopacket"
|
|
)
|
|
|
|
var graphPkgs []GraphPkg
|
|
|
|
// AddPkgToGraph adds the given packet as communication to the graph
|
|
func AddPkgToGraph(pkg gopacket.Packet) {
|
|
// Only proceed if pkg contains a network layer
|
|
if pkg.NetworkLayer() == nil {
|
|
return
|
|
}
|
|
|
|
src := pkg.NetworkLayer().NetworkFlow().Src().String()
|
|
dst := pkg.NetworkLayer().NetworkFlow().Dst().String()
|
|
|
|
// Search for the given communication pair
|
|
for _, p := range graphPkgs {
|
|
if p.from == src && p.to == dst {
|
|
// Communication pair found, add protocol and finish
|
|
p.AddProtocol("nil")
|
|
return
|
|
}
|
|
}
|
|
|
|
// Communcation pair was not in graphPkgs, add to it
|
|
graphPkgs = append(graphPkgs, GraphPkg{
|
|
from: src,
|
|
to: dst,
|
|
protocol: []string{""},
|
|
})
|
|
}
|
|
|
|
// CreateGraph writes out a Graphviz digraph
|
|
func CreateGraph() {
|
|
if *graphOutput == "" {
|
|
// No graph requested
|
|
return
|
|
}
|
|
|
|
// Start with the Graphviz-specific header
|
|
dot := fmt.Sprintf("# Compile with `neato -Tpng %s > %s.png`\n", *graphOutput, *graphOutput)
|
|
dot += "digraph pancap {\n\toverlap = false;\n"
|
|
|
|
// First, gather all nodes as-is and write them out
|
|
dot += nodedef(graphPkgs)
|
|
|
|
// Iterate over communication
|
|
for _, p := range graphPkgs {
|
|
dot += fmt.Sprintf("\tn%s->n%s\n", hash(p.from), hash(p.to))
|
|
}
|
|
|
|
// Close
|
|
dot += "}\n"
|
|
|
|
// Write out
|
|
ioutil.WriteFile(*graphOutput, []byte(dot), 0644)
|
|
}
|
|
|
|
// Creates a list of distinct nodes, Graphviz-compatible
|
|
func nodedef(pkgs []GraphPkg) string {
|
|
output := ""
|
|
nodes := []string{}
|
|
for _, p := range graphPkgs {
|
|
// Check if src and dst are already present in nodes array
|
|
srcFound := false
|
|
dstFound := false
|
|
for _, n := range nodes {
|
|
if p.from == n {
|
|
srcFound = true
|
|
}
|
|
if p.to == n {
|
|
dstFound = true
|
|
}
|
|
}
|
|
if !srcFound {
|
|
// src not yet present, add to node list
|
|
nodes = append(nodes, p.from)
|
|
}
|
|
if !dstFound {
|
|
// dst not yet present, add to node list
|
|
nodes = append(nodes, p.to)
|
|
}
|
|
}
|
|
|
|
// Output Graphviz-compatible node definition
|
|
for _, n := range nodes {
|
|
// As the Graphviz charset for nodes is rather small, rely on hashes
|
|
output += fmt.Sprintf("\tn%s[label=\"%s\"]\n", hash(n), n)
|
|
}
|
|
|
|
return output
|
|
}
|
|
|
|
func hash(s string) string {
|
|
return fmt.Sprintf("%x", sha256.Sum256([]byte(s)))[:6]
|
|
}
|