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 }