Merge pull request #4 from neilalexander/master

Some code to draw graphviz dot graphs of your view of the network
This commit is contained in:
Arceliar 2018-01-21 12:14:31 -06:00 committed by GitHub
commit 8973d3c86d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 155 additions and 15 deletions

124
src/yggdrasil/admin.go Normal file
View File

@ -0,0 +1,124 @@
package yggdrasil
import "net"
import "os"
import "bytes"
import "fmt"
// TODO: Make all of this JSON
// TODO: Add authentication
// TODO: Is any of this thread safe?
type admin struct {
core *Core
listenaddr string
}
func (a *admin) init(c *Core, listenaddr string) {
a.core = c
a.listenaddr = listenaddr
go a.listen()
}
func (a *admin) listen() {
l, err := net.Listen("tcp", a.listenaddr)
if err != nil {
a.core.log.Printf("Admin socket failed to listen: %v", err)
os.Exit(1)
}
defer l.Close()
a.core.log.Printf("Admin socket listening on %s", l.Addr().String())
for {
conn, err := l.Accept()
if err == nil {
a.handleRequest(conn)
}
}
}
func (a *admin) handleRequest(conn net.Conn) {
buf := make([]byte, 1024)
_, err := conn.Read(buf)
if err != nil {
a.core.log.Printf("Admin socket failed to read: %v", err)
conn.Close()
return
}
buf = bytes.Trim(buf, "\x00\r\n\t")
switch string(buf) {
case "dot":
const mDepth = 1024
m := make(map[[mDepth]switchPort]string)
table := a.core.switchTable.table.Load().(lookupTable)
peers := a.core.peers.ports.Load().(map[switchPort]*peer)
// Add my own entry
peerID := address_addrForNodeID(getNodeID(&peers[0].box))
addr := net.IP(peerID[:]).String()
var index [mDepth]switchPort
copy(index[:mDepth], table.self.coords[:])
m[index] = addr
// Connect switch table entries to peer entries
for _, tableentry := range table.elems {
for _, peerentry := range peers {
if peerentry.port == tableentry.port {
peerID := address_addrForNodeID(getNodeID(&peerentry.box))
addr := net.IP(peerID[:]).String()
var index [mDepth]switchPort
copy(index[:mDepth], tableentry.locator.coords[:])
m[index] = addr
}
}
}
// Look up everything we know from DHT
for i := 0; i < a.core.dht.nBuckets(); i++ {
b := a.core.dht.getBucket(i)
for _, v := range b.infos {
var destPorts []switchPort
for offset := 0; ; {
coord, length := wire_decode_uint64(v.coords[offset:])
if length == 0 {
break
}
destPorts = append(destPorts, switchPort(coord))
offset += length
}
addr := net.IP(address_addrForNodeID(v.nodeID_hidden)[:]).String()
var index [mDepth]switchPort
copy(index[:mDepth], destPorts[:])
m[index] = addr
}
}
// Now print it all out
conn.Write([]byte(fmt.Sprintf("graph {\n")))
for k := range m {
var mask [mDepth]switchPort
copy(mask[:mDepth], k[:])
for mk := range mask {
mask[len(mask)-1-mk] = 0
if len(m[k]) == 0 {
m[k] = fmt.Sprintf("%+v (missing)", k)
}
if len(m[mask]) == 0 {
m[mask] = fmt.Sprintf("%+v (missing)", mask)
}
if len(m[mask]) > 0 && m[mask] != m[k] {
conn.Write([]byte(fmt.Sprintf(" \"%+v\" -- \"%+v\";\n", m[k], m[mask])))
break
}
}
}
conn.Write([]byte(fmt.Sprintf("}\n")))
break
default:
conn.Write([]byte("I didn't understand that!\n"))
}
if err != nil {
a.core.log.Printf("Admin socket error: %v", err)
}
conn.Close()
}

View File

@ -20,6 +20,7 @@ type Core struct {
router router router router
dht dht dht dht
tun tunDevice tun tunDevice
admin admin
searches searches searches searches
tcp *tcpInterface tcp *tcpInterface
udp *udpInterface udp *udpInterface

View File

@ -336,6 +336,14 @@ func (c *Core) DEBUG_addKCPConn(saddr string) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
func (c *Core) DEBUG_setupAndStartAdminInterface(addrport string) {
a := admin{}
a.init(c, addrport)
c.admin = a
}
////////////////////////////////////////////////////////////////////////////////
func (c *Core) DEBUG_setLogger(log *log.Logger) { func (c *Core) DEBUG_setLogger(log *log.Logger) {
c.log = log c.log = log
} }

View File

@ -150,7 +150,7 @@ func (r *router) sendPacket(bs []byte) {
} }
func (r *router) recvPacket(bs []byte, theirAddr *address, theirSubnet *subnet) { func (r *router) recvPacket(bs []byte, theirAddr *address, theirSubnet *subnet) {
// TODO? move this into the session? // TODO? move this into the session?
//fmt.Println("Recv packet") //fmt.Println("Recv packet")
if len(bs) < 24 { if len(bs) < 24 {
util_putBytes(bs) util_putBytes(bs)

View File

@ -44,13 +44,13 @@ type in6_aliasreq struct {
ifra_addr sockaddr_in6 ifra_addr sockaddr_in6
ifra_dstaddr sockaddr_in6 ifra_dstaddr sockaddr_in6
ifra_prefixmask sockaddr_in6 ifra_prefixmask sockaddr_in6
ifra_flags uint32 ifra_flags uint32
ifra_lifetime in6_addrlifetime ifra_lifetime in6_addrlifetime
} }
type ifreq struct { type ifreq struct {
ifr_name [16]byte ifr_name [16]byte
ifru_mtu uint32 ifru_mtu uint32
} }
func (tun *tunDevice) setupAddress(addr string) error { func (tun *tunDevice) setupAddress(addr string) error {
@ -66,7 +66,8 @@ func (tun *tunDevice) setupAddress(addr string) error {
copy(ar.ifra_name[:], tun.iface.Name()) copy(ar.ifra_name[:], tun.iface.Name())
ar.ifra_prefixmask.sin6_len = uint8(unsafe.Sizeof(ar.ifra_prefixmask)) ar.ifra_prefixmask.sin6_len = uint8(unsafe.Sizeof(ar.ifra_prefixmask))
b := make([]byte, 16); binary.LittleEndian.PutUint16(b, uint16(0xFF00)) b := make([]byte, 16)
binary.LittleEndian.PutUint16(b, uint16(0xFF00))
ar.ifra_prefixmask.sin6_addr[0] = uint16(binary.BigEndian.Uint16(b)) ar.ifra_prefixmask.sin6_addr[0] = uint16(binary.BigEndian.Uint16(b))
ar.ifra_addr.sin6_len = uint8(unsafe.Sizeof(ar.ifra_addr)) ar.ifra_addr.sin6_len = uint8(unsafe.Sizeof(ar.ifra_addr))
@ -74,7 +75,8 @@ func (tun *tunDevice) setupAddress(addr string) error {
parts := strings.Split(strings.TrimRight(addr, "/8"), ":") parts := strings.Split(strings.TrimRight(addr, "/8"), ":")
for i := 0; i < 8; i++ { for i := 0; i < 8; i++ {
addr, _ := strconv.ParseUint(parts[i], 16, 16) addr, _ := strconv.ParseUint(parts[i], 16, 16)
b := make([]byte, 16); binary.LittleEndian.PutUint16(b, uint16(addr)) b := make([]byte, 16)
binary.LittleEndian.PutUint16(b, uint16(addr))
ar.ifra_addr.sin6_addr[i] = uint16(binary.BigEndian.Uint16(b)) ar.ifra_addr.sin6_addr[i] = uint16(binary.BigEndian.Uint16(b))
} }

View File

@ -29,15 +29,16 @@ import . "yggdrasil"
*/ */
type nodeConfig struct { type nodeConfig struct {
Listen string Listen string
Peers []string AdminListen string
BoxPub string Peers []string
BoxPriv string BoxPub string
SigPub string BoxPriv string
SigPriv string SigPub string
Multicast bool SigPriv string
LinkLocal string Multicast bool
IfName string LinkLocal string
IfName string
} }
type node struct { type node struct {
@ -72,6 +73,9 @@ func (n *node) init(cfg *nodeConfig, logger *log.Logger) {
logger.Println("Starting interface...") logger.Println("Starting interface...")
n.core.DEBUG_setupAndStartGlobalUDPInterface(cfg.Listen) n.core.DEBUG_setupAndStartGlobalUDPInterface(cfg.Listen)
logger.Println("Started interface") logger.Println("Started interface")
logger.Println("Starting admin socket...")
n.core.DEBUG_setupAndStartAdminInterface(cfg.AdminListen)
logger.Println("Started admin socket")
go func() { go func() {
if len(cfg.Peers) == 0 { if len(cfg.Peers) == 0 {
return return
@ -92,6 +96,7 @@ func generateConfig() *nodeConfig {
spub, spriv := core.DEBUG_newSigKeys() spub, spriv := core.DEBUG_newSigKeys()
cfg := nodeConfig{} cfg := nodeConfig{}
cfg.Listen = "[::]:0" cfg.Listen = "[::]:0"
cfg.AdminListen = "[::1]:9001"
cfg.BoxPub = hex.EncodeToString(bpub[:]) cfg.BoxPub = hex.EncodeToString(bpub[:])
cfg.BoxPriv = hex.EncodeToString(bpriv[:]) cfg.BoxPriv = hex.EncodeToString(bpriv[:])
cfg.SigPub = hex.EncodeToString(spub[:]) cfg.SigPub = hex.EncodeToString(spub[:])