From b754d68068991db7bc5683bcbb18f2ba9954a2ce Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sun, 21 Jan 2018 00:17:15 +0000 Subject: [PATCH 1/4] Add an admin socket --- src/yggdrasil/admin.go | 61 +++++++++++++++++++++++++++++++++++++ src/yggdrasil/core.go | 1 + src/yggdrasil/debug.go | 8 +++++ src/yggdrasil/router.go | 2 +- src/yggdrasil/tun_darwin.go | 12 +++++--- yggdrasil.go | 23 ++++++++------ 6 files changed, 92 insertions(+), 15 deletions(-) create mode 100644 src/yggdrasil/admin.go diff --git a/src/yggdrasil/admin.go b/src/yggdrasil/admin.go new file mode 100644 index 00000000..b7a6e74a --- /dev/null +++ b/src/yggdrasil/admin.go @@ -0,0 +1,61 @@ +package yggdrasil + +import "net" +import "os" +import "bytes" +import "fmt" + +// TODO: Make all of this JSON + +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 "ports": + ports := a.core.peers.getPorts() + for _, v := range ports { + conn.Write([]byte(fmt.Sprintf("Found switch port %d\n", v.port))) + } + 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() +} diff --git a/src/yggdrasil/core.go b/src/yggdrasil/core.go index 464477e4..08aa594c 100644 --- a/src/yggdrasil/core.go +++ b/src/yggdrasil/core.go @@ -20,6 +20,7 @@ type Core struct { router router dht dht tun tunDevice + admin admin searches searches tcp *tcpInterface udp *udpInterface diff --git a/src/yggdrasil/debug.go b/src/yggdrasil/debug.go index e182276d..ead8918b 100644 --- a/src/yggdrasil/debug.go +++ b/src/yggdrasil/debug.go @@ -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) { c.log = log } diff --git a/src/yggdrasil/router.go b/src/yggdrasil/router.go index 61f25605..668181de 100644 --- a/src/yggdrasil/router.go +++ b/src/yggdrasil/router.go @@ -150,7 +150,7 @@ func (r *router) sendPacket(bs []byte) { } 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") if len(bs) < 24 { util_putBytes(bs) diff --git a/src/yggdrasil/tun_darwin.go b/src/yggdrasil/tun_darwin.go index df191355..fde6c1ee 100644 --- a/src/yggdrasil/tun_darwin.go +++ b/src/yggdrasil/tun_darwin.go @@ -44,13 +44,13 @@ type in6_aliasreq struct { ifra_addr sockaddr_in6 ifra_dstaddr sockaddr_in6 ifra_prefixmask sockaddr_in6 - ifra_flags uint32 + ifra_flags uint32 ifra_lifetime in6_addrlifetime } type ifreq struct { - ifr_name [16]byte - ifru_mtu uint32 + ifr_name [16]byte + ifru_mtu uint32 } 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()) 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_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"), ":") for i := 0; i < 8; i++ { 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)) } diff --git a/yggdrasil.go b/yggdrasil.go index bb0de1fc..90002893 100644 --- a/yggdrasil.go +++ b/yggdrasil.go @@ -29,15 +29,16 @@ import . "yggdrasil" */ type nodeConfig struct { - Listen string - Peers []string - BoxPub string - BoxPriv string - SigPub string - SigPriv string - Multicast bool - LinkLocal string - IfName string + Listen string + AdminListen string + Peers []string + BoxPub string + BoxPriv string + SigPub string + SigPriv string + Multicast bool + LinkLocal string + IfName string } type node struct { @@ -72,6 +73,9 @@ func (n *node) init(cfg *nodeConfig, logger *log.Logger) { logger.Println("Starting interface...") n.core.DEBUG_setupAndStartGlobalUDPInterface(cfg.Listen) logger.Println("Started interface") + logger.Println("Starting admin socket...") + n.core.DEBUG_setupAndStartAdminInterface(cfg.AdminListen) + logger.Println("Started admin socket") go func() { if len(cfg.Peers) == 0 { return @@ -92,6 +96,7 @@ func generateConfig() *nodeConfig { spub, spriv := core.DEBUG_newSigKeys() cfg := nodeConfig{} cfg.Listen = "[::]:0" + cfg.AdminListen = "[::]:0" cfg.BoxPub = hex.EncodeToString(bpub[:]) cfg.BoxPriv = hex.EncodeToString(bpriv[:]) cfg.SigPub = hex.EncodeToString(spub[:]) From c4ac0a90ac8250a87981ac97b608e58c22520c75 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sun, 21 Jan 2018 12:57:54 +0000 Subject: [PATCH 2/4] Add the ability to see switch ports and DHT --- src/yggdrasil/admin.go | 34 ++++++++++++++++++++++++++++++---- yggdrasil.go | 2 +- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/yggdrasil/admin.go b/src/yggdrasil/admin.go index b7a6e74a..86ac1001 100644 --- a/src/yggdrasil/admin.go +++ b/src/yggdrasil/admin.go @@ -6,6 +6,8 @@ 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 @@ -44,10 +46,34 @@ func (a *admin) handleRequest(conn net.Conn) { } buf = bytes.Trim(buf, "\x00\r\n\t") switch string(buf) { - case "ports": - ports := a.core.peers.getPorts() - for _, v := range ports { - conn.Write([]byte(fmt.Sprintf("Found switch port %d\n", v.port))) + case "switch table": + table := a.core.switchTable.table.Load().(lookupTable) + conn.Write([]byte(fmt.Sprintf( + "port 0 -> %+v\n", + table.self.coords))) + for _, v := range table.elems { + conn.Write([]byte(fmt.Sprintf( + "port %d -> %+v\n", + v.port, + v.locator.coords))) + } + break + + case "dht": + n := a.core.dht.nBuckets() + for i := 0; i < n; i++ { + b := a.core.dht.getBucket(i) + if len(b.infos) == 0 { + continue + } + for _, v := range b.infos { + addr := address_addrForNodeID(v.nodeID_hidden) + ip := net.IP(addr[:]).String() + + conn.Write([]byte(fmt.Sprintf("%+v -> %+v\n", + ip, + v.coords))) + } } break diff --git a/yggdrasil.go b/yggdrasil.go index 90002893..cde55c55 100644 --- a/yggdrasil.go +++ b/yggdrasil.go @@ -96,7 +96,7 @@ func generateConfig() *nodeConfig { spub, spriv := core.DEBUG_newSigKeys() cfg := nodeConfig{} cfg.Listen = "[::]:0" - cfg.AdminListen = "[::]:0" + cfg.AdminListen = "[::1]:9001" cfg.BoxPub = hex.EncodeToString(bpub[:]) cfg.BoxPriv = hex.EncodeToString(bpriv[:]) cfg.SigPub = hex.EncodeToString(spub[:]) From 483d90a7288cbdd5d4155eb7d45392ee16227092 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sun, 21 Jan 2018 17:51:51 +0000 Subject: [PATCH 3/4] Draw dot draphs (although maybe not very well) --- src/yggdrasil/admin.go | 81 ++++++++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 23 deletions(-) diff --git a/src/yggdrasil/admin.go b/src/yggdrasil/admin.go index 86ac1001..26a3f9b1 100644 --- a/src/yggdrasil/admin.go +++ b/src/yggdrasil/admin.go @@ -46,35 +46,70 @@ func (a *admin) handleRequest(conn net.Conn) { } buf = bytes.Trim(buf, "\x00\r\n\t") switch string(buf) { - case "switch table": + case "dot": + const mDepth = 1024 + m := make(map[[mDepth]switchPort]string) table := a.core.switchTable.table.Load().(lookupTable) - conn.Write([]byte(fmt.Sprintf( - "port 0 -> %+v\n", - table.self.coords))) - for _, v := range table.elems { - conn.Write([]byte(fmt.Sprintf( - "port %d -> %+v\n", - v.port, - v.locator.coords))) - } - break + peers := a.core.peers.ports.Load().(map[switchPort]*peer) - case "dht": - n := a.core.dht.nBuckets() - for i := 0; i < n; i++ { + // 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) - if len(b.infos) == 0 { - continue - } for _, v := range b.infos { - addr := address_addrForNodeID(v.nodeID_hidden) - ip := net.IP(addr[:]).String() - - conn.Write([]byte(fmt.Sprintf("%+v -> %+v\n", - ip, - v.coords))) + 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: From 8ef852469b5ba41d7e1eeb92f736f03118e08edf Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sun, 21 Jan 2018 17:53:25 +0000 Subject: [PATCH 4/4] Formatting --- src/yggdrasil/admin.go | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/yggdrasil/admin.go b/src/yggdrasil/admin.go index 26a3f9b1..5576a365 100644 --- a/src/yggdrasil/admin.go +++ b/src/yggdrasil/admin.go @@ -73,20 +73,22 @@ func (a *admin) handleRequest(conn net.Conn) { } // Look up everything we know from DHT - for i := 0; i < a.core.dht.nBuckets(); i++ { + 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 + 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 } } @@ -97,15 +99,15 @@ func (a *admin) handleRequest(conn net.Conn) { 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[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 + break } } }