mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 11:15:07 +03: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
					
				
					 2 changed files with 95 additions and 3 deletions
				
			
		| 
						 | 
					@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue