Permalink
Browse files

Crawling now working

  • Loading branch information...
urban
urban committed Apr 8, 2017
1 parent bceda33 commit 60a319a21ad00c4cc7ac8cf913dbf165c8364247
Showing with 186 additions and 44 deletions.
  1. +125 −0 graph.go
  2. +13 −9 main.go
  3. +48 −35 network_devices.go
125 graph.go
@@ -0,0 +1,125 @@
package main
import (
"fmt"
// "sync"
)
type GraphError struct {
action, message string
}
func (e *GraphError) Error() string {
return fmt.Sprintf("Error in %s: %s", e.action, e.message)
}
// NetworkGraph
type NetworkGraph struct {
nodes map[IPAddr]NetworkDevice
edges []Port
}
func NewNetworkGraph() NetworkGraph {
return NetworkGraph{
nodes: make(map[IPAddr]NetworkDevice),
}
}
func (ng *NetworkGraph) GetNode(id IPAddr) (NetworkDevice, error) {
if node, ok := ng.nodes[id]; ok {
return node, nil
} else {
return nil, &GraphError{
"GetNode",
fmt.Sprintf("Node %s doesn't exist!", id),
}
}
}
func (ng *NetworkGraph) GetNodes() map[IPAddr]NetworkDevice {
return ng.nodes
}
func (ng *NetworkGraph) GetNodesCount() int {
return len(ng.nodes)
}
func (ng *NetworkGraph) AddNode(addr IPAddr, node NetworkDevice) error {
if _, ok := ng.nodes[addr]; ok {
return &GraphError{
"AddNode",
fmt.Sprintf("Node with address %s already exists in the graph.", addr),
}
} else {
ng.nodes[addr] = node
return nil
}
}
func (ng *NetworkGraph) CrawlOnce(startID IPAddr) []IPAddr {
startNode, _ := ng.GetNode(startID)
neighbors := []IPAddr{}
for port, ip := range startNode.GetNeighbors() {
if _, node_exists := ng.nodes[ip]; !node_exists {
ng.AddNode(ip, NewNetworkSwitch(ip))
}
ng.edges = append(ng.edges, Port{
LocalPort: port,
RemotePort: 0,
LocalAddress: startID,
RemoteAddress: ip,
})
neighbors = append(neighbors, ip)
}
return neighbors
}
func (ng *NetworkGraph) GetEdges() []Port {
return ng.edges
}
func (ng *NetworkGraph) CrawlRecursively(id IPAddr) []IPAddr {
if _, err := ng.GetNode(id); err != nil {
return nil
}
visited := make(map[IPAddr]bool)
nodes := []IPAddr{}
ng.dfsCrawl(id, visited, &nodes)
return nodes
}
func (ng *NetworkGraph) dfsCrawl(id IPAddr, visited map[IPAddr]bool, nodes *[]IPAddr) {
if _, ok := visited[id]; ok {
return
}
visited[id] = true
*nodes = append(*nodes, id)
startNode, _ := ng.GetNode(id)
for port, ip := range startNode.GetNeighbors() {
if _, node_exists := ng.nodes[ip]; !node_exists {
ng.AddNode(ip, NewNetworkSwitch(ip))
}
ng.edges = append(ng.edges, Port{
LocalPort: port,
RemotePort: 0,
LocalAddress: id,
RemoteAddress: ip,
})
ng.dfsCrawl(ip, visited, nodes)
}
}
22 main.go
@@ -1,19 +1,23 @@
package main
import "fmt"
import (
"fmt"
// "github.com/gonum/graph"
// "github.com/gonum/graph/simple"
)
var ports = make(map[int]*Port)
var switches = make(map[string]*NetworkSwitch)
// var ports = make(map[int]*Port)
var switches = make(map[IPAddr]*NetworkSwitch)
func main() {
startIP := "10.1.1.0"
startIP := IPAddr("10.1.1.0")
startSwitch := NewNetworkSwitch(startIP)
switches[startIP] = startSwitch
startSwitch.FindRemotes()
network := NewNetworkGraph()
network.AddNode(startIP, startSwitch)
network.CrawlRecursively(startIP)
fmt.Printf("Found %d nodes!\n", network.GetNodesCount())
fmt.Printf("%s", network.GetEdges())
for index, nswitch := range switches {
fmt.Printf("* Switch %s: %s\n", index, nswitch.ShowPorts())
}
}
@@ -10,85 +10,98 @@ import (
gosnmp "github.com/soniah/gosnmp"
)
type IPAddr string
// Port
type Port struct {
RemoteSwitch *NetworkSwitch
RemoteAddress IPAddr
RemotePort int
LocalAddress IPAddr
LocalPort int
}
func (p Port) String() string {
return fmt.Sprintf("%s:%02d\t->\t%s\n", p.LocalAddress, p.LocalPort, p.RemoteAddress)
}
// interface NetworkDevice
type NetworkDevice interface {
GetIP() IPAddr
GetNeighbors() map[int]IPAddr
}
// NetworkSwitch
type NetworkSwitch struct {
IP string
Ports map[int]*Port
IP IPAddr
Ports map[int]IPAddr
}
func NewNetworkSwitch(IP string) *NetworkSwitch {
func NewNetworkSwitch(IP IPAddr) *NetworkSwitch {
return &NetworkSwitch{
IP: IP,
Ports: make(map[int]*Port),
Ports: make(map[int]IPAddr),
}
}
func (n NetworkSwitch) FindRemotes() {
func (n NetworkSwitch) GetIP() IPAddr {
return n.IP
}
func (n NetworkSwitch) String() string {
return fmt.Sprintf("\nSwitch: %s (%d connections)\n", n.IP, len(n.Ports))
}
func (n *NetworkSwitch) GetNeighbors() map[int]IPAddr {
snmpConnection := &gosnmp.GoSNMP{
Target: n.IP,
Target: string(n.IP),
Port: 161,
Community: "DS-public",
Version: gosnmp.Version2c,
Timeout: time.Duration(2) * time.Second,
}
fmt.Printf("Trying %s...", n.GetIP())
err := snmpConnection.Connect()
if err != nil {
log.Fatalf("Connect() err: %v", err)
} else {
defer snmpConnection.Conn.Close()
}
defer snmpConnection.Conn.Close()
lldpOid := "1.0.8802.1.1.2.1.4.2.1"
err2 := snmpConnection.BulkWalk(lldpOid, n.interpretValue)
if err2 != nil {
log.Fatalf("Get() err: %v", err2)
fmt.Println(" error, ignoring...")
} else {
fmt.Println("")
}
// fmt.Printf("%s", n.Ports)
}
func (n NetworkSwitch) String() string {
return fmt.Sprintf("Switch: %s\nPorts: %s", n.IP, n.Ports)
return n.Ports
}
func (n NetworkSwitch) ShowPorts() string {
return fmt.Sprintf("%s", n.Ports)
}
func (p Port) String() string {
return fmt.Sprintf("Remote IP:%s\n", p.RemoteSwitch.IP)
}
func (n *NetworkSwitch) interpretValue(pdu gosnmp.SnmpPDU) error {
func (n NetworkSwitch) unpackPduName(s string) (int, string) {
splitOid := str.Split(s, ".")
splitOid := str.Split(pdu.Name, ".")
portId, err := strconv.Atoi(splitOid[13])
if err != nil {
// handle error
fmt.Println(err)
}
remoteIP := str.Join(splitOid[17:], ".")
return portId, remoteIP
}
func (n *NetworkSwitch) interpretValue(pdu gosnmp.SnmpPDU) error {
portId, remoteIP := n.unpackPduName(pdu.Name)
nswitch, ok := switches[remoteIP]
if !ok {
nswitch = NewNetworkSwitch(remoteIP)
switches[remoteIP] = nswitch
}
remoteIP := IPAddr(str.Join(splitOid[17:], "."))
_, ok = n.Ports[portId]
if !ok {
n.Ports[portId] = &Port{nswitch}
if _, ok := n.Ports[portId]; !ok {
n.Ports[portId] = remoteIP
}
return nil

0 comments on commit 60a319a

Please sign in to comment.