mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2024-11-23 18:15:24 +00:00
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:
commit
8973d3c86d
124
src/yggdrasil/admin.go
Normal file
124
src/yggdrasil/admin.go
Normal 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()
|
||||||
|
}
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
23
yggdrasil.go
23
yggdrasil.go
@ -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[:])
|
||||||
|
Loading…
Reference in New Issue
Block a user