2017-12-29 04:16:20 +00:00
package main
import "encoding/hex"
import "flag"
import "fmt"
import "io/ioutil"
import "net"
import "os"
import "os/signal"
2018-02-18 21:16:47 +00:00
import "syscall"
2017-12-29 04:16:20 +00:00
import "time"
2018-01-09 08:08:54 +00:00
import "regexp"
2018-03-07 19:41:56 +00:00
import "math/rand"
2017-12-29 04:16:20 +00:00
import _ "net/http/pprof"
import "net/http"
import "log"
import "runtime"
2018-04-19 14:30:40 +00:00
import "yggdrasil"
import "yggdrasil/config"
2017-12-29 04:16:20 +00:00
2018-02-18 21:16:47 +00:00
import "github.com/kardianos/minwinsvc"
2018-05-09 12:54:31 +00:00
import "github.com/neilalexander/hjson-go"
import "github.com/mitchellh/mapstructure"
2018-02-16 14:12:44 +00:00
2018-04-19 14:30:40 +00:00
type nodeConfig = config . NodeConfig
type Core = yggdrasil . Core
2017-12-29 04:16:20 +00:00
type node struct {
2018-01-04 22:37:51 +00:00
core Core
2017-12-29 04:16:20 +00:00
}
func ( n * node ) init ( cfg * nodeConfig , logger * log . Logger ) {
2018-01-04 22:37:51 +00:00
boxPub , err := hex . DecodeString ( cfg . BoxPub )
if err != nil {
panic ( err )
}
boxPriv , err := hex . DecodeString ( cfg . BoxPriv )
if err != nil {
panic ( err )
}
sigPub , err := hex . DecodeString ( cfg . SigPub )
if err != nil {
panic ( err )
}
sigPriv , err := hex . DecodeString ( cfg . SigPriv )
if err != nil {
panic ( err )
}
n . core . DEBUG_init ( boxPub , boxPriv , sigPub , sigPriv )
n . core . DEBUG_setLogger ( logger )
2018-04-19 14:30:40 +00:00
2018-01-04 22:37:51 +00:00
logger . Println ( "Starting interface..." )
2018-02-09 23:42:55 +00:00
n . core . DEBUG_setupAndStartGlobalTCPInterface ( cfg . Listen ) // Listen for peers on TCP
2018-02-10 00:50:03 +00:00
n . core . DEBUG_setupAndStartGlobalUDPInterface ( cfg . Listen ) // Also listen on UDP, TODO allow separate configuration for ip/port to listen on each of these
2018-01-04 22:37:51 +00:00
logger . Println ( "Started interface" )
2018-01-21 00:17:15 +00:00
logger . Println ( "Starting admin socket..." )
n . core . DEBUG_setupAndStartAdminInterface ( cfg . AdminListen )
logger . Println ( "Started admin socket" )
2018-05-07 22:05:54 +00:00
for _ , pBoxStr := range cfg . AllowedBoxPubs {
n . core . DEBUG_addAllowedBoxPub ( pBoxStr )
2018-05-07 00:48:26 +00:00
}
2018-05-23 10:13:53 +00:00
logger . Println ( cfg . LinkLocal )
for _ , ll := range cfg . LinkLocal {
logger . Println ( "Adding expression" , ll )
ifceExpr , err := regexp . Compile ( ll )
if err != nil {
panic ( err )
}
logger . Println ( "Added expression" , ifceExpr )
n . core . DEBUG_setIfceExpr ( ifceExpr )
}
n . core . DEBUG_setupAndStartMulticastInterface ( )
2018-05-07 00:48:26 +00:00
2018-01-04 22:37:51 +00:00
go func ( ) {
if len ( cfg . Peers ) == 0 {
return
}
for {
for _ , p := range cfg . Peers {
2018-04-26 14:23:21 +00:00
n . core . DEBUG_addPeer ( p )
2018-01-04 22:37:51 +00:00
time . Sleep ( time . Second )
}
time . Sleep ( time . Minute )
}
} ( )
2017-12-29 04:16:20 +00:00
}
2018-03-07 19:41:56 +00:00
func generateConfig ( isAutoconf bool ) * nodeConfig {
2018-01-04 22:37:51 +00:00
core := Core { }
bpub , bpriv := core . DEBUG_newBoxKeys ( )
spub , spriv := core . DEBUG_newSigKeys ( )
cfg := nodeConfig { }
2018-03-07 19:41:56 +00:00
if isAutoconf {
cfg . Listen = "[::]:0"
} else {
r1 := rand . New ( rand . NewSource ( time . Now ( ) . UnixNano ( ) ) )
2018-03-10 19:58:48 +00:00
cfg . Listen = fmt . Sprintf ( "[::]:%d" , r1 . Intn ( 65534 - 32768 ) + 32768 )
2018-03-07 19:41:56 +00:00
}
2018-02-11 21:45:44 +00:00
cfg . AdminListen = "[::1]:9001"
2018-01-04 22:37:51 +00:00
cfg . BoxPub = hex . EncodeToString ( bpub [ : ] )
cfg . BoxPriv = hex . EncodeToString ( bpriv [ : ] )
cfg . SigPub = hex . EncodeToString ( spub [ : ] )
cfg . SigPriv = hex . EncodeToString ( spriv [ : ] )
cfg . Peers = [ ] string { }
2018-05-07 22:05:54 +00:00
cfg . AllowedBoxPubs = [ ] string { }
2018-05-23 10:13:53 +00:00
cfg . Multicast = false
cfg . LinkLocal = [ ] string { }
2018-03-03 12:30:54 +00:00
cfg . IfName = core . DEBUG_GetTUNDefaultIfName ( )
cfg . IfMTU = core . DEBUG_GetTUNDefaultIfMTU ( )
cfg . IfTAPMode = core . DEBUG_GetTUNDefaultIfTAPMode ( )
2018-04-19 14:30:40 +00:00
2018-01-04 22:37:51 +00:00
return & cfg
2017-12-29 04:16:20 +00:00
}
func doGenconf ( ) string {
2018-03-07 19:41:56 +00:00
cfg := generateConfig ( false )
2018-05-09 12:54:31 +00:00
bs , err := hjson . Marshal ( cfg )
2018-01-04 22:37:51 +00:00
if err != nil {
panic ( err )
}
return string ( bs )
2017-12-29 04:16:20 +00:00
}
var pprof = flag . Bool ( "pprof" , false , "Run pprof, see http://localhost:6060/debug/pprof/" )
var genconf = flag . Bool ( "genconf" , false , "print a new config to stdout" )
var useconf = flag . Bool ( "useconf" , false , "read config from stdin" )
2018-02-16 14:12:44 +00:00
var useconffile = flag . String ( "useconffile" , "" , "read config from specified file path" )
2017-12-29 04:16:20 +00:00
var autoconf = flag . Bool ( "autoconf" , false , "automatic mode (dynamic IP, peer with IPv6 neighbors)" )
func main ( ) {
2018-01-04 22:37:51 +00:00
flag . Parse ( )
var cfg * nodeConfig
switch {
case * autoconf :
2018-03-07 19:41:56 +00:00
cfg = generateConfig ( true )
2018-02-16 14:12:44 +00:00
case * useconffile != "" || * useconf :
var config [ ] byte
var err error
if * useconffile != "" {
config , err = ioutil . ReadFile ( * useconffile )
} else {
config , err = ioutil . ReadAll ( os . Stdin )
}
2018-01-04 22:37:51 +00:00
if err != nil {
panic ( err )
}
2018-03-07 19:41:56 +00:00
cfg = generateConfig ( false )
2018-05-09 12:54:31 +00:00
var dat map [ string ] interface { }
if err := hjson . Unmarshal ( config , & dat ) ; err != nil {
2018-05-09 13:03:28 +00:00
panic ( err )
}
2018-05-09 12:54:31 +00:00
if err = mapstructure . Decode ( dat , & cfg ) ; err != nil {
2018-01-04 22:37:51 +00:00
panic ( err )
}
case * genconf :
fmt . Println ( doGenconf ( ) )
default :
flag . PrintDefaults ( )
}
if cfg == nil {
return
}
logger := log . New ( os . Stdout , "" , log . Flags ( ) )
if * pprof {
runtime . SetBlockProfileRate ( 1 )
go func ( ) { log . Println ( http . ListenAndServe ( "localhost:6060" , nil ) ) } ( )
}
// Setup
logger . Println ( "Initializing..." )
n := node { }
n . init ( cfg , logger )
2018-02-15 22:29:13 +00:00
if cfg . IfName != "none" {
logger . Println ( "Starting TUN/TAP..." )
} else {
logger . Println ( "Not starting TUN/TAP" )
}
2018-02-04 17:25:20 +00:00
//n.core.DEBUG_startTun(cfg.IfName) // 1280, the smallest supported MTU
2018-02-14 12:53:32 +00:00
n . core . DEBUG_startTunWithMTU ( cfg . IfName , cfg . IfTAPMode , cfg . IfMTU ) // Largest supported MTU
2018-01-04 22:37:51 +00:00
defer func ( ) {
logger . Println ( "Closing..." )
n . core . DEBUG_stopTun ( )
} ( )
logger . Println ( "Started..." )
2018-05-21 15:15:31 +00:00
address := ( * n . core . GetAddress ( ) ) [ : ]
subnet := ( * n . core . GetSubnet ( ) ) [ : ]
subnet = append ( subnet , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 )
logger . Printf ( "Your IPv6 address is %s" , net . IP ( address ) . String ( ) )
logger . Printf ( "Your IPv6 subnet is %s/64" , net . IP ( subnet ) . String ( ) )
2018-01-04 22:37:51 +00:00
// Catch interrupt to exit gracefully
c := make ( chan os . Signal , 1 )
2018-02-18 21:16:47 +00:00
signal . Notify ( c , os . Interrupt , syscall . SIGTERM )
// Create a function to capture the service being stopped on Windows
winTerminate := func ( ) {
2018-02-18 21:32:55 +00:00
c <- os . Interrupt
}
2018-02-18 21:16:47 +00:00
minwinsvc . SetOnExit ( winTerminate )
// Wait for the terminate/interrupt signal
2018-01-04 22:37:51 +00:00
<- c
logger . Println ( "Stopping..." )
2017-12-29 04:16:20 +00:00
}