github.com/yggdrasil-network/yggdrasil-go@v0.5.6/src/ipv6rwc/ipv6rwc.go (about)

     1  package ipv6rwc
     2  
     3  import (
     4  	"crypto/ed25519"
     5  	"errors"
     6  	"fmt"
     7  	"net"
     8  	"sync"
     9  	"time"
    10  
    11  	"golang.org/x/net/icmp"
    12  	"golang.org/x/net/ipv6"
    13  
    14  	iwt "github.com/Arceliar/ironwood/types"
    15  
    16  	"github.com/yggdrasil-network/yggdrasil-go/src/address"
    17  	"github.com/yggdrasil-network/yggdrasil-go/src/core"
    18  )
    19  
    20  const keyStoreTimeout = 2 * time.Minute
    21  
    22  /*
    23  // Out-of-band packet types
    24  const (
    25  	typeKeyDummy = iota // nolint:deadcode,varcheck
    26  	typeKeyLookup
    27  	typeKeyResponse
    28  )
    29  */
    30  
    31  type keyArray [ed25519.PublicKeySize]byte
    32  
    33  type keyStore struct {
    34  	core         *core.Core
    35  	address      address.Address
    36  	subnet       address.Subnet
    37  	mutex        sync.Mutex
    38  	keyToInfo    map[keyArray]*keyInfo
    39  	addrToInfo   map[address.Address]*keyInfo
    40  	addrBuffer   map[address.Address]*buffer
    41  	subnetToInfo map[address.Subnet]*keyInfo
    42  	subnetBuffer map[address.Subnet]*buffer
    43  	mtu          uint64
    44  }
    45  
    46  type keyInfo struct {
    47  	key     keyArray
    48  	address address.Address
    49  	subnet  address.Subnet
    50  	timeout *time.Timer // From calling a time.AfterFunc to do cleanup
    51  }
    52  
    53  type buffer struct {
    54  	packet  []byte
    55  	timeout *time.Timer
    56  }
    57  
    58  func (k *keyStore) init(c *core.Core) {
    59  	k.core = c
    60  	k.address = *address.AddrForKey(k.core.PublicKey())
    61  	k.subnet = *address.SubnetForKey(k.core.PublicKey())
    62  	/*if err := k.core.SetOutOfBandHandler(k.oobHandler); err != nil {
    63  		err = fmt.Errorf("tun.core.SetOutOfBandHander: %w", err)
    64  		panic(err)
    65  	}*/
    66  	k.core.SetPathNotify(func(key ed25519.PublicKey) {
    67  		k.update(key)
    68  	})
    69  	k.keyToInfo = make(map[keyArray]*keyInfo)
    70  	k.addrToInfo = make(map[address.Address]*keyInfo)
    71  	k.addrBuffer = make(map[address.Address]*buffer)
    72  	k.subnetToInfo = make(map[address.Subnet]*keyInfo)
    73  	k.subnetBuffer = make(map[address.Subnet]*buffer)
    74  	k.mtu = 1280 // Default to something safe, expect user to set this
    75  }
    76  
    77  func (k *keyStore) sendToAddress(addr address.Address, bs []byte) {
    78  	k.mutex.Lock()
    79  	if info := k.addrToInfo[addr]; info != nil {
    80  		k.resetTimeout(info)
    81  		k.mutex.Unlock()
    82  		_, _ = k.core.WriteTo(bs, iwt.Addr(info.key[:]))
    83  	} else {
    84  		var buf *buffer
    85  		if buf = k.addrBuffer[addr]; buf == nil {
    86  			buf = new(buffer)
    87  			k.addrBuffer[addr] = buf
    88  		}
    89  		msg := append([]byte(nil), bs...)
    90  		buf.packet = msg
    91  		if buf.timeout != nil {
    92  			buf.timeout.Stop()
    93  		}
    94  		buf.timeout = time.AfterFunc(keyStoreTimeout, func() {
    95  			k.mutex.Lock()
    96  			defer k.mutex.Unlock()
    97  			if nbuf := k.addrBuffer[addr]; nbuf == buf {
    98  				delete(k.addrBuffer, addr)
    99  			}
   100  		})
   101  		k.mutex.Unlock()
   102  		k.sendKeyLookup(addr.GetKey())
   103  	}
   104  }
   105  
   106  func (k *keyStore) sendToSubnet(subnet address.Subnet, bs []byte) {
   107  	k.mutex.Lock()
   108  	if info := k.subnetToInfo[subnet]; info != nil {
   109  		k.resetTimeout(info)
   110  		k.mutex.Unlock()
   111  		_, _ = k.core.WriteTo(bs, iwt.Addr(info.key[:]))
   112  	} else {
   113  		var buf *buffer
   114  		if buf = k.subnetBuffer[subnet]; buf == nil {
   115  			buf = new(buffer)
   116  			k.subnetBuffer[subnet] = buf
   117  		}
   118  		msg := append([]byte(nil), bs...)
   119  		buf.packet = msg
   120  		if buf.timeout != nil {
   121  			buf.timeout.Stop()
   122  		}
   123  		buf.timeout = time.AfterFunc(keyStoreTimeout, func() {
   124  			k.mutex.Lock()
   125  			defer k.mutex.Unlock()
   126  			if nbuf := k.subnetBuffer[subnet]; nbuf == buf {
   127  				delete(k.subnetBuffer, subnet)
   128  			}
   129  		})
   130  		k.mutex.Unlock()
   131  		k.sendKeyLookup(subnet.GetKey())
   132  	}
   133  }
   134  
   135  func (k *keyStore) update(key ed25519.PublicKey) *keyInfo {
   136  	k.mutex.Lock()
   137  	var kArray keyArray
   138  	copy(kArray[:], key)
   139  	var info *keyInfo
   140  	var packets [][]byte
   141  	if info = k.keyToInfo[kArray]; info == nil {
   142  		info = new(keyInfo)
   143  		info.key = kArray
   144  		info.address = *address.AddrForKey(ed25519.PublicKey(info.key[:]))
   145  		info.subnet = *address.SubnetForKey(ed25519.PublicKey(info.key[:]))
   146  		k.keyToInfo[info.key] = info
   147  		k.addrToInfo[info.address] = info
   148  		k.subnetToInfo[info.subnet] = info
   149  		if buf := k.addrBuffer[info.address]; buf != nil {
   150  			packets = append(packets, buf.packet)
   151  			delete(k.addrBuffer, info.address)
   152  		}
   153  		if buf := k.subnetBuffer[info.subnet]; buf != nil {
   154  			packets = append(packets, buf.packet)
   155  			delete(k.subnetBuffer, info.subnet)
   156  		}
   157  	}
   158  	k.resetTimeout(info)
   159  	k.mutex.Unlock()
   160  	for _, packet := range packets {
   161  		_, _ = k.core.WriteTo(packet, iwt.Addr(info.key[:]))
   162  	}
   163  	return info
   164  }
   165  
   166  func (k *keyStore) resetTimeout(info *keyInfo) {
   167  	if info.timeout != nil {
   168  		info.timeout.Stop()
   169  	}
   170  	info.timeout = time.AfterFunc(keyStoreTimeout, func() {
   171  		k.mutex.Lock()
   172  		defer k.mutex.Unlock()
   173  		if nfo := k.keyToInfo[info.key]; nfo == info {
   174  			delete(k.keyToInfo, info.key)
   175  		}
   176  		if nfo := k.addrToInfo[info.address]; nfo == info {
   177  			delete(k.addrToInfo, info.address)
   178  		}
   179  		if nfo := k.subnetToInfo[info.subnet]; nfo == info {
   180  			delete(k.subnetToInfo, info.subnet)
   181  		}
   182  	})
   183  }
   184  
   185  /*
   186  func (k *keyStore) oobHandler(fromKey, toKey ed25519.PublicKey, data []byte) { // nolint:unused
   187  	if len(data) != 1+ed25519.SignatureSize {
   188  		return
   189  	}
   190  	sig := data[1:]
   191  	switch data[0] {
   192  	case typeKeyLookup:
   193  		snet := *address.SubnetForKey(toKey)
   194  		if snet == k.subnet && ed25519.Verify(fromKey, toKey[:], sig) {
   195  			// This is looking for at least our subnet (possibly our address)
   196  			// Send a response
   197  			k.sendKeyResponse(fromKey)
   198  		}
   199  	case typeKeyResponse:
   200  		// TODO keep a list of something to match against...
   201  		// Ignore the response if it doesn't match anything of interest...
   202  		if ed25519.Verify(fromKey, toKey[:], sig) {
   203  			k.update(fromKey)
   204  		}
   205  	}
   206  }
   207  */
   208  
   209  func (k *keyStore) sendKeyLookup(partial ed25519.PublicKey) {
   210  	/*
   211  		sig := ed25519.Sign(k.core.PrivateKey(), partial[:])
   212  		bs := append([]byte{typeKeyLookup}, sig...)
   213  		//_ = k.core.SendOutOfBand(partial, bs)
   214  		_ = bs
   215  	*/
   216  	k.core.SendLookup(partial)
   217  }
   218  
   219  /*
   220  func (k *keyStore) sendKeyResponse(dest ed25519.PublicKey) { // nolint:unused
   221  	sig := ed25519.Sign(k.core.PrivateKey(), dest[:])
   222  	bs := append([]byte{typeKeyResponse}, sig...)
   223  	//_ = k.core.SendOutOfBand(dest, bs)
   224  	_ = bs
   225  }
   226  */
   227  
   228  func (k *keyStore) readPC(p []byte) (int, error) {
   229  	buf := make([]byte, k.core.MTU(), 65535)
   230  	for {
   231  		bs := buf
   232  		n, from, err := k.core.ReadFrom(bs)
   233  		if err != nil {
   234  			return n, err
   235  		}
   236  		if n == 0 {
   237  			continue
   238  		}
   239  		bs = bs[:n]
   240  		if len(bs) == 0 {
   241  			continue
   242  		}
   243  		if bs[0]&0xf0 != 0x60 {
   244  			continue // not IPv6
   245  		}
   246  		if len(bs) < 40 {
   247  			continue
   248  		}
   249  		k.mutex.Lock()
   250  		mtu := int(k.mtu)
   251  		k.mutex.Unlock()
   252  		if len(bs) > mtu {
   253  			// Using bs would make it leak off the stack, so copy to buf
   254  			buf := make([]byte, 512)
   255  			cn := copy(buf, bs)
   256  			ptb := &icmp.PacketTooBig{
   257  				MTU:  mtu,
   258  				Data: buf[:cn],
   259  			}
   260  			if packet, err := CreateICMPv6(buf[8:24], buf[24:40], ipv6.ICMPTypePacketTooBig, 0, ptb); err == nil {
   261  				_, _ = k.writePC(packet)
   262  			}
   263  			continue
   264  		}
   265  		var srcAddr, dstAddr address.Address
   266  		var srcSubnet, dstSubnet address.Subnet
   267  		copy(srcAddr[:], bs[8:])
   268  		copy(dstAddr[:], bs[24:])
   269  		copy(srcSubnet[:], bs[8:])
   270  		copy(dstSubnet[:], bs[24:])
   271  		if dstAddr != k.address && dstSubnet != k.subnet {
   272  			continue // bad local address/subnet
   273  		}
   274  		info := k.update(ed25519.PublicKey(from.(iwt.Addr)))
   275  		if srcAddr != info.address && srcSubnet != info.subnet {
   276  			continue // bad remote address/subnet
   277  		}
   278  		n = copy(p, bs)
   279  		return n, nil
   280  	}
   281  }
   282  
   283  func (k *keyStore) writePC(bs []byte) (int, error) {
   284  	if bs[0]&0xf0 != 0x60 {
   285  		return 0, errors.New("not an IPv6 packet") // not IPv6
   286  	}
   287  	if len(bs) < 40 {
   288  		strErr := fmt.Sprint("undersized IPv6 packet, length: ", len(bs))
   289  		return 0, errors.New(strErr)
   290  	}
   291  	var srcAddr, dstAddr address.Address
   292  	var srcSubnet, dstSubnet address.Subnet
   293  	copy(srcAddr[:], bs[8:])
   294  	copy(dstAddr[:], bs[24:])
   295  	copy(srcSubnet[:], bs[8:])
   296  	copy(dstSubnet[:], bs[24:])
   297  	if srcAddr != k.address && srcSubnet != k.subnet {
   298  		// This happens all the time due to link-local traffic
   299  		// Don't send back an error, just drop it
   300  		strErr := fmt.Sprint("incorrect source address: ", net.IP(srcAddr[:]).String())
   301  		return 0, errors.New(strErr)
   302  	}
   303  	if dstAddr.IsValid() {
   304  		k.sendToAddress(dstAddr, bs)
   305  	} else if dstSubnet.IsValid() {
   306  		k.sendToSubnet(dstSubnet, bs)
   307  	} else {
   308  		return 0, errors.New("invalid destination address")
   309  	}
   310  	return len(bs), nil
   311  }
   312  
   313  // Exported API
   314  
   315  func (k *keyStore) MaxMTU() uint64 {
   316  	return k.core.MTU()
   317  }
   318  
   319  func (k *keyStore) SetMTU(mtu uint64) {
   320  	if mtu > k.MaxMTU() {
   321  		mtu = k.MaxMTU()
   322  	}
   323  	if mtu < 1280 {
   324  		mtu = 1280
   325  	}
   326  	k.mutex.Lock()
   327  	k.mtu = mtu
   328  	k.mutex.Unlock()
   329  }
   330  
   331  func (k *keyStore) MTU() uint64 {
   332  	k.mutex.Lock()
   333  	mtu := k.mtu
   334  	k.mutex.Unlock()
   335  	return mtu
   336  }
   337  
   338  type ReadWriteCloser struct {
   339  	keyStore
   340  }
   341  
   342  func NewReadWriteCloser(c *core.Core) *ReadWriteCloser {
   343  	rwc := new(ReadWriteCloser)
   344  	rwc.init(c)
   345  	return rwc
   346  }
   347  
   348  func (rwc *ReadWriteCloser) Address() address.Address {
   349  	return rwc.address
   350  }
   351  
   352  func (rwc *ReadWriteCloser) Subnet() address.Subnet {
   353  	return rwc.subnet
   354  }
   355  
   356  func (rwc *ReadWriteCloser) Read(p []byte) (n int, err error) {
   357  	return rwc.readPC(p)
   358  }
   359  
   360  func (rwc *ReadWriteCloser) Write(p []byte) (n int, err error) {
   361  	return rwc.writePC(p)
   362  }
   363  
   364  func (rwc *ReadWriteCloser) Close() error {
   365  	err := rwc.core.Close()
   366  	rwc.core.Stop()
   367  	return err
   368  }