From 024037541741696e22527f7c93cead4a94ea6e70 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Tue, 6 Nov 2018 20:49:19 +0000 Subject: [PATCH] IPv4 CKR support in router --- src/yggdrasil/ckr.go | 34 +++++++++++++++++++--------- src/yggdrasil/router.go | 50 ++++++++++++++++++++++++++++++----------- src/yggdrasil/tun.go | 2 +- 3 files changed, 62 insertions(+), 24 deletions(-) diff --git a/src/yggdrasil/ckr.go b/src/yggdrasil/ckr.go index 8036486b..f22840c3 100644 --- a/src/yggdrasil/ckr.go +++ b/src/yggdrasil/ckr.go @@ -46,22 +46,36 @@ func (c *cryptokey) isEnabled() bool { return c.enabled } -func (c *cryptokey) isValidSource(addr address) bool { - ip := net.IP(addr[:]) +func (c *cryptokey) isValidSource(addr address, addrlen int) bool { + ip := net.IP(addr[:addrlen]) - // Does this match our node's address? - if bytes.Equal(addr[:16], c.core.router.addr[:16]) { - return true - } + if addrlen == net.IPv6len { + // Does this match our node's address? + if bytes.Equal(addr[:16], c.core.router.addr[:16]) { + return true + } - // Does this match our node's subnet? - if bytes.Equal(addr[:8], c.core.router.subnet[:8]) { - return true + // Does this match our node's subnet? + if bytes.Equal(addr[:8], c.core.router.subnet[:8]) { + return true + } } // Does it match a configured CKR source? if c.isEnabled() { - for _, subnet := range c.ipv6sources { + // Build our references to the routing sources + var routingsources *[]net.IPNet + + // Check if the prefix is IPv4 or IPv6 + if addrlen == net.IPv6len { + routingsources = &c.ipv6sources + } else if addrlen == net.IPv4len { + routingsources = &c.ipv4sources + } else { + return false + } + + for _, subnet := range *routingsources { if subnet.Contains(ip) { return true } diff --git a/src/yggdrasil/router.go b/src/yggdrasil/router.go index cd922a9c..0c633acc 100644 --- a/src/yggdrasil/router.go +++ b/src/yggdrasil/router.go @@ -127,14 +127,26 @@ func (r *router) sendPacket(bs []byte) { var sourceAddr address var dest address var snet subnet - copy(sourceAddr[:], bs[8:]) - if !r.cryptokey.isValidSource(sourceAddr) { + var addrlen int + if bs[0]&0xf0 == 0x60 { + // IPv6 address + addrlen = 16 + copy(sourceAddr[:addrlen], bs[8:]) + copy(dest[:addrlen], bs[24:]) + copy(snet[:addrlen/2], bs[24:]) + } else if bs[0]&0xf0 == 0x40 { + // IPv4 address + addrlen = 4 + copy(sourceAddr[:addrlen], bs[12:]) + copy(dest[:addrlen], bs[16:]) + } else { + return + } + if !r.cryptokey.isValidSource(sourceAddr, addrlen) { return } - copy(dest[:], bs[24:]) - copy(snet[:], bs[24:]) if !dest.isValid() && !snet.isValid() { - if key, err := r.cryptokey.getPublicKeyForAddress(dest, 16); err == nil { + if key, err := r.cryptokey.getPublicKeyForAddress(dest, addrlen); err == nil { addr := *address_addrForNodeID(getNodeID(&key)) copy(dest[:], addr[:]) copy(snet[:], addr[:]) @@ -259,21 +271,33 @@ func (r *router) recvPacket(bs []byte, sinfo *sessionInfo) { util_putBytes(bs) return } + var sourceAddr address var dest address - copy(dest[:], bs[24:]) - if !r.cryptokey.isValidSource(dest) { + var snet subnet + var addrlen int + if bs[0]&0xf0 == 0x60 { + // IPv6 address + addrlen = 16 + copy(sourceAddr[:addrlen], bs[8:]) + copy(dest[:addrlen], bs[24:]) + copy(snet[:addrlen/2], bs[24:]) + } else if bs[0]&0xf0 == 0x40 { + // IPv4 address + addrlen = 4 + copy(sourceAddr[:addrlen], bs[12:]) + copy(dest[:addrlen], bs[16:]) + } else { + return + } + if !r.cryptokey.isValidSource(dest, addrlen) { util_putBytes(bs) return } - var source address - copy(source[:], bs[8:]) - var snet subnet - copy(snet[:], bs[8:]) switch { - case source.isValid() && source == sinfo.theirAddr: + case sourceAddr.isValid() && sourceAddr == sinfo.theirAddr: case snet.isValid() && snet == sinfo.theirSubnet: default: - key, err := r.cryptokey.getPublicKeyForAddress(source, 16) + key, err := r.cryptokey.getPublicKeyForAddress(sourceAddr, addrlen) if err != nil || key != sinfo.theirPermPub { util_putBytes(bs) return diff --git a/src/yggdrasil/tun.go b/src/yggdrasil/tun.go index cbbcdea7..ac703985 100644 --- a/src/yggdrasil/tun.go +++ b/src/yggdrasil/tun.go @@ -105,7 +105,7 @@ func (tun *tunDevice) read() error { n != 256*int(buf[o+4])+int(buf[o+5])+tun_IPv6_HEADER_LENGTH+o { // Either not an IPv6 packet or not the complete packet for some reason //panic("Should not happen in testing") - continue + //continue } if buf[o+6] == 58 { // Found an ICMPv6 packet