Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions addrmgr/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,12 +264,21 @@ func IsValid(na *wire.NetAddress) bool {
// in any reserved ranges.
func IsRoutable(na *wire.NetAddressV2) bool {
if na.IsTorV3() {
// na is a torv3 address, return true.
return true
}

// Else na can be represented as a legacy NetAddress since i2p and
// cjdns are unsupported.
if na.IsI2P() {
return false
}

if na.IsCJDNS() {
return false
}

if na.IsYggdrasil() {
return false
}

lna := na.ToLegacy()
return IsValid(lna) && !(IsRFC1918(lna) || IsRFC2544(lna) ||
IsRFC3927(lna) || IsRFC4862(lna) || IsRFC3849(lna) ||
Expand Down
117 changes: 106 additions & 11 deletions wire/netaddressv2.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,11 @@ var (
// maximum size for an unknown networkID.
ErrInvalidAddressSize = fmt.Errorf("invalid address size")

// ErrSkippedNetworkID is returned when the cjdns, i2p, or unknown
// networks are encountered during decoding. btcd does not support i2p
// or cjdns addresses. In the case of an unknown networkID, this is so
// that a future BIP reserving a new networkID does not cause older
// addrv2-supporting btcd software to disconnect upon receiving the new
// addresses. This error can also be returned when an OnionCat-encoded
// torv2 address is received with the ipv6 networkID. This error
// signals to the caller to continue reading.
// ErrSkippedNetworkID is returned when an unknown network ID is
// encountered during decoding, or when an OnionCat-encoded torv2 address
// is received with the ipv6 networkID. This allows future BIP-reserved
// networkIDs to be silently skipped rather than causing a disconnect.
// It signals to the caller to continue reading the message.
ErrSkippedNetworkID = fmt.Errorf("skipped networkID")
)

Expand Down Expand Up @@ -148,6 +145,27 @@ func (na *NetAddressV2) IsTorV3() bool {
return ok
}

// IsI2P returns a bool that signals to the caller whether or not this is an
// i2p address.
func (na *NetAddressV2) IsI2P() bool {
_, ok := na.Addr.(*i2pAddr)
return ok
}

// IsCJDNS returns a bool that signals to the caller whether or not this is a
// cjdns address.
func (na *NetAddressV2) IsCJDNS() bool {
_, ok := na.Addr.(*cjdnsAddr)
return ok
}

// IsYggdrasil returns a bool that signals to the caller whether or not this is
// a yggdrasil address.
func (na *NetAddressV2) IsYggdrasil() bool {
_, ok := na.Addr.(*yggdrasilAddr)
return ok
}

// TorV3Key returns the first byte of the v3 public key. This is used in the
// addrmgr to calculate a key from a network group.
func (na *NetAddressV2) TorV3Key() byte {
Expand Down Expand Up @@ -247,6 +265,15 @@ func writeNetAddressV2(w io.Writer, pver uint32, na *NetAddressV2) error {
case *torv3Addr:
netID = a.netID
address = a.addr[:]
case *i2pAddr:
netID = a.netID
address = a.addr[:]
case *cjdnsAddr:
netID = a.netID
address = a.addr[:]
case *yggdrasilAddr:
netID = a.netID
address = a.addr[:]
default:
// This should not occur.
return fmt.Errorf("unexpected address type")
Expand Down Expand Up @@ -418,7 +445,7 @@ func readNetAddressV2(r io.Reader, pver uint32, na *NetAddressV2) error {
return err
}

return ErrSkippedNetworkID
na.Addr = addr
case cjdns:
addr := &cjdnsAddr{}
addr.netID = cjdns
Expand All @@ -435,7 +462,24 @@ func readNetAddressV2(r io.Reader, pver uint32, na *NetAddressV2) error {
return err
}

return ErrSkippedNetworkID
na.Addr = addr
case yggdrasil:
addr := &yggdrasilAddr{}
addr.netID = yggdrasil
if decodedSize != uint64(yggdrasilSize) {
return ErrInvalidAddressSize
}

if err := readElement(r, &addr.addr); err != nil {
return err
}

na.Port, err = binarySerializer.Uint16(r, bigEndian)
if err != nil {
return err
}

na.Addr = addr
}

return nil
Expand Down Expand Up @@ -463,6 +507,9 @@ const (

// cjdns means the following address is a cjdns address.
cjdns

// yggdrasil means the following address is a yggdrasil address.
yggdrasil
)

const (
Expand All @@ -483,6 +530,9 @@ const (

// cjdnsSize is the size of a cjdns address.
cjdnsSize = 16

// yggdrasilSize is the size of a yggdrasil address.
yggdrasilSize = 16
)

const (
Expand All @@ -498,7 +548,7 @@ const (
// isKnownNetworkID returns true if the networkID is one listed above and false
// otherwise.
func isKnownNetworkID(netID uint8) bool {
return uint8(ipv4) <= netID && netID <= uint8(cjdns)
return uint8(ipv4) <= netID && netID <= uint8(yggdrasil)
}

type ipv4Addr struct {
Expand Down Expand Up @@ -612,7 +662,52 @@ type i2pAddr struct {
netID networkID
}

// Part of the net.Addr interface.
func (a *i2pAddr) String() string {
b32 := base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(a.addr[:])
return strings.ToLower(b32) + ".b32.i2p"
}

// Part of the net.Addr interface.
func (a *i2pAddr) Network() string {
return string(a.netID)
}

// Compile-time constraint to check that i2pAddr meets the net.Addr interface.
var _ net.Addr = (*i2pAddr)(nil)

type cjdnsAddr struct {
addr [cjdnsSize]byte
netID networkID
}

// Part of the net.Addr interface.
func (a *cjdnsAddr) String() string {
return net.IP(a.addr[:]).String()
}

// Part of the net.Addr interface.
func (a *cjdnsAddr) Network() string {
return string(a.netID)
}

// Compile-time constraint to check that cjdnsAddr meets the net.Addr interface.
var _ net.Addr = (*cjdnsAddr)(nil)

type yggdrasilAddr struct {
addr [yggdrasilSize]byte
netID networkID
}

// Part of the net.Addr interface.
func (a *yggdrasilAddr) String() string {
return net.IP(a.addr[:]).String()
}

// Part of the net.Addr interface.
func (a *yggdrasilAddr) Network() string {
return string(a.netID)
}

// Compile-time constraint to check that yggdrasilAddr meets the net.Addr interface.
var _ net.Addr = (*yggdrasilAddr)(nil)