mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-25 21:51:38 +00:00
add a udp close packet, and partial support for a removePeer admin call (sends close to UDP peers, but doesn't close TCP connections yet)
This commit is contained in:
parent
96399d586d
commit
0459f88b92
@ -3,6 +3,7 @@ package yggdrasil
|
|||||||
import "net"
|
import "net"
|
||||||
import "os"
|
import "os"
|
||||||
import "bytes"
|
import "bytes"
|
||||||
|
import "errors"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "sort"
|
import "sort"
|
||||||
import "strings"
|
import "strings"
|
||||||
@ -63,6 +64,13 @@ func (a *admin) init(c *Core, listenaddr string) {
|
|||||||
*out = []byte("Failed to add peer: " + saddr[0] + "\n")
|
*out = []byte("Failed to add peer: " + saddr[0] + "\n")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
a.addHandler("removePeer", []string{"<peer>"}, func(out *[]byte, saddr ...string) {
|
||||||
|
if a.removePeer(saddr[0]) == nil {
|
||||||
|
*out = []byte("Removing peer: " + saddr[0] + "\n")
|
||||||
|
} else {
|
||||||
|
*out = []byte("Failed to remove peer: " + saddr[0] + "\n")
|
||||||
|
}
|
||||||
|
})
|
||||||
a.addHandler("setTunTap", []string{"<ifname|auto|none>", "[<tun|tap>]", "[<mtu>]"}, func(out *[]byte, ifparams ...string) {
|
a.addHandler("setTunTap", []string{"<ifname|auto|none>", "[<tun|tap>]", "[<mtu>]"}, func(out *[]byte, ifparams ...string) {
|
||||||
// Set sane defaults
|
// Set sane defaults
|
||||||
iftapmode := false
|
iftapmode := false
|
||||||
@ -216,6 +224,30 @@ func (a *admin) addPeer(p string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *admin) removePeer(p string) error {
|
||||||
|
pAddr := p
|
||||||
|
if p[:4] == "tcp:" || p[:4] == "udp:" {
|
||||||
|
pAddr = p[4:]
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case len(p) >= 4 && p[:4] == "udp:":
|
||||||
|
// Connect to peer over UDP
|
||||||
|
udpAddr, err := net.ResolveUDPAddr("udp", pAddr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var addr connAddr
|
||||||
|
addr.fromUDPAddr(udpAddr)
|
||||||
|
a.core.udp.sendClose(addr)
|
||||||
|
return nil
|
||||||
|
case len(p) >= 4 && p[:4] == "tcp:":
|
||||||
|
default:
|
||||||
|
// Connect to peer over TCP
|
||||||
|
return errors.New("Removing TCP peer not yet supported")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *admin) startTunWithMTU(ifname string, iftapmode bool, ifmtu int) error {
|
func (a *admin) startTunWithMTU(ifname string, iftapmode bool, ifmtu int) error {
|
||||||
// Close the TUN first if open
|
// Close the TUN first if open
|
||||||
_ = a.core.tun.close()
|
_ = a.core.tun.close()
|
||||||
|
@ -51,6 +51,7 @@ type connInfo struct {
|
|||||||
peer *peer
|
peer *peer
|
||||||
linkIn chan []byte
|
linkIn chan []byte
|
||||||
keysIn chan *udpKeys
|
keysIn chan *udpKeys
|
||||||
|
closeIn chan *udpKeys
|
||||||
timeout int // count of how many heartbeats have been missed
|
timeout int // count of how many heartbeats have been missed
|
||||||
in func([]byte)
|
in func([]byte)
|
||||||
out chan []byte
|
out chan []byte
|
||||||
@ -87,9 +88,23 @@ func (iface *udpInterface) sendKeys(addr connAddr) {
|
|||||||
iface.sock.WriteToUDP(msg, udpAddr)
|
iface.sock.WriteToUDP(msg, udpAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (iface *udpInterface) sendClose(addr connAddr) {
|
||||||
|
udpAddr := addr.toUDPAddr()
|
||||||
|
msg := []byte{}
|
||||||
|
msg = udp_encode(msg, 0, 1, 0, nil)
|
||||||
|
msg = append(msg, iface.core.boxPub[:]...)
|
||||||
|
msg = append(msg, iface.core.sigPub[:]...)
|
||||||
|
iface.sock.WriteToUDP(msg, udpAddr)
|
||||||
|
}
|
||||||
|
|
||||||
func udp_isKeys(msg []byte) bool {
|
func udp_isKeys(msg []byte) bool {
|
||||||
keyLen := 3 + boxPubKeyLen + sigPubKeyLen
|
keyLen := 3 + boxPubKeyLen + sigPubKeyLen
|
||||||
return len(msg) == keyLen && msg[0] == 0x00
|
return len(msg) == keyLen && msg[0] == 0x00 && msg[1] == 0x00
|
||||||
|
}
|
||||||
|
|
||||||
|
func udp_isClose(msg []byte) bool {
|
||||||
|
keyLen := 3 + boxPubKeyLen + sigPubKeyLen
|
||||||
|
return len(msg) == keyLen && msg[0] == 0x00 && msg[1] == 0x01
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iface *udpInterface) startConn(info *connInfo) {
|
func (iface *udpInterface) startConn(info *connInfo) {
|
||||||
@ -111,11 +126,21 @@ func (iface *udpInterface) startConn(info *connInfo) {
|
|||||||
iface.core.peers.mutex.Unlock()
|
iface.core.peers.mutex.Unlock()
|
||||||
close(info.linkIn)
|
close(info.linkIn)
|
||||||
close(info.keysIn)
|
close(info.keysIn)
|
||||||
|
close(info.closeIn)
|
||||||
close(info.out)
|
close(info.out)
|
||||||
|
iface.sendClose(info.addr)
|
||||||
iface.core.log.Println("Removing peer:", info.name)
|
iface.core.log.Println("Removing peer:", info.name)
|
||||||
}()
|
}()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
case ks := <-info.closeIn:
|
||||||
|
{
|
||||||
|
if ks.box == info.peer.box && ks.sig == info.peer.sig {
|
||||||
|
// TODO? secure this somehow
|
||||||
|
// Maybe add a signature and sequence number (timestamp) to close and keys?
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
case ks := <-info.keysIn:
|
case ks := <-info.keysIn:
|
||||||
{
|
{
|
||||||
// FIXME? need signatures/sequence-numbers or something
|
// FIXME? need signatures/sequence-numbers or something
|
||||||
@ -136,6 +161,37 @@ func (iface *udpInterface) startConn(info *connInfo) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (iface *udpInterface) handleClose(msg []byte, addr connAddr) {
|
||||||
|
//defer util_putBytes(msg)
|
||||||
|
var ks udpKeys
|
||||||
|
_, _, _, bs := udp_decode(msg)
|
||||||
|
switch {
|
||||||
|
case !wire_chop_slice(ks.box[:], &bs):
|
||||||
|
return
|
||||||
|
case !wire_chop_slice(ks.sig[:], &bs):
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ks.box == iface.core.boxPub {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ks.sig == iface.core.sigPub {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
iface.mutex.RLock()
|
||||||
|
conn, isIn := iface.conns[addr]
|
||||||
|
iface.mutex.RUnlock()
|
||||||
|
if !isIn {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func() {
|
||||||
|
defer func() { recover() }()
|
||||||
|
select {
|
||||||
|
case conn.closeIn <- &ks:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) {
|
func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) {
|
||||||
//defer util_putBytes(msg)
|
//defer util_putBytes(msg)
|
||||||
var ks udpKeys
|
var ks udpKeys
|
||||||
@ -167,6 +223,7 @@ func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) {
|
|||||||
peer: iface.core.peers.newPeer(&ks.box, &ks.sig),
|
peer: iface.core.peers.newPeer(&ks.box, &ks.sig),
|
||||||
linkIn: make(chan []byte, 1),
|
linkIn: make(chan []byte, 1),
|
||||||
keysIn: make(chan *udpKeys, 1),
|
keysIn: make(chan *udpKeys, 1),
|
||||||
|
closeIn: make(chan *udpKeys, 1),
|
||||||
out: make(chan []byte, 32),
|
out: make(chan []byte, 32),
|
||||||
chunkSize: 576 - 60 - 8 - 3, // max safe - max ip - udp header - chunk overhead
|
chunkSize: 576 - 60 - 8 - 3, // max safe - max ip - udp header - chunk overhead
|
||||||
}
|
}
|
||||||
@ -277,7 +334,8 @@ func (iface *udpInterface) reader() {
|
|||||||
msg := bs[:n]
|
msg := bs[:n]
|
||||||
var addr connAddr
|
var addr connAddr
|
||||||
addr.fromUDPAddr(udpAddr)
|
addr.fromUDPAddr(udpAddr)
|
||||||
if udp_isKeys(msg) {
|
switch {
|
||||||
|
case udp_isKeys(msg):
|
||||||
var them address
|
var them address
|
||||||
copy(them[:], udpAddr.IP.To16())
|
copy(them[:], udpAddr.IP.To16())
|
||||||
if them.isValid() {
|
if them.isValid() {
|
||||||
@ -288,7 +346,9 @@ func (iface *udpInterface) reader() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
iface.handleKeys(msg, addr)
|
iface.handleKeys(msg, addr)
|
||||||
} else {
|
case udp_isClose(msg):
|
||||||
|
iface.handleClose(msg, addr)
|
||||||
|
default:
|
||||||
iface.handlePacket(msg, addr)
|
iface.handlePacket(msg, addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user