mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-24 20:53:07 +02:00
unwrap dns addresses from opaque ones during migration
This commit is contained in:
@@ -46,6 +46,71 @@ var (
|
|||||||
Payload: []byte{0xff, 0x02, 0x03, 0x04, 0x05, 0x06},
|
Payload: []byte{0xff, 0x02, 0x03, 0x04, 0x05, 0x06},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testOpaqueAddrWithEmbeddedDNSAddr = &lnwire.OpaqueAddrs{
|
||||||
|
Payload: []byte{
|
||||||
|
/* Here we embed an actual DNS address */
|
||||||
|
// The protocol level type for DNS addresses.
|
||||||
|
0x05,
|
||||||
|
// Hostname length: 11.
|
||||||
|
0x0B,
|
||||||
|
// The hostname itself.
|
||||||
|
'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm',
|
||||||
|
// port 8080 in big-endian.
|
||||||
|
0x1F, 0x90,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
testOpaqueAddrWithTwoEmbeddedDNSAddrs = &lnwire.OpaqueAddrs{
|
||||||
|
Payload: []byte{
|
||||||
|
/* Here we embed an actual DNS address */
|
||||||
|
// The protocol level type for DNS addresses.
|
||||||
|
0x05,
|
||||||
|
// Hostname length: 11.
|
||||||
|
0x0B,
|
||||||
|
// The hostname itself.
|
||||||
|
'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm',
|
||||||
|
// port 8080 in big-endian.
|
||||||
|
0x1F, 0x90,
|
||||||
|
// Another DNS address.
|
||||||
|
0x05,
|
||||||
|
0x0B,
|
||||||
|
'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm',
|
||||||
|
0x1F, 0x90,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
testOpaqueAddrWithEmbeddedDNSAddrAndMore = &lnwire.OpaqueAddrs{
|
||||||
|
Payload: []byte{
|
||||||
|
/* Here we embed an actual DNS address */
|
||||||
|
// The protocol level type for DNS addresses.
|
||||||
|
0x05,
|
||||||
|
// Hostname length: 11.
|
||||||
|
0x0B,
|
||||||
|
// The hostname itself.
|
||||||
|
'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm',
|
||||||
|
// port 8080 in big-endian.
|
||||||
|
0x1F, 0x90,
|
||||||
|
// Now we add more opaque bytes to represent more
|
||||||
|
// addresses that we dont know about yet.
|
||||||
|
// NOTE: the 0xff is an address type that we definitely
|
||||||
|
// don't know about yet
|
||||||
|
0xff, 0x02, 0x03, 0x04, 0x05, 0x06,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
testOpaqueAddrWithEmbeddedBadDNSAddr = &lnwire.OpaqueAddrs{
|
||||||
|
Payload: []byte{
|
||||||
|
/* Here we embed an actual invalid DNS address */
|
||||||
|
// The protocol level type for DNS addresses.
|
||||||
|
0x05,
|
||||||
|
// Hostname length: We set this to a size that is
|
||||||
|
// incorrect in order to simulate the bad DNS address.
|
||||||
|
0xAA,
|
||||||
|
// The hostname itself.
|
||||||
|
'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm',
|
||||||
|
// port 9735 in big-endian.
|
||||||
|
0x26, 0x07,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
testDNSAddr = &lnwire.DNSAddress{
|
testDNSAddr = &lnwire.DNSAddress{
|
||||||
Hostname: "example.com",
|
Hostname: "example.com",
|
||||||
Port: 8080,
|
Port: 8080,
|
||||||
|
@@ -263,14 +263,41 @@ func migrateNodes(ctx context.Context, cfg *sqldb.QueryConfig,
|
|||||||
count++
|
count++
|
||||||
chunk++
|
chunk++
|
||||||
|
|
||||||
// TODO(elle): At this point, we should check the loaded node
|
addrs := make([]net.Addr, 0, len(node.Addresses))
|
||||||
// to see if we should extract any DNS addresses from its
|
for _, addr := range node.Addresses {
|
||||||
// opaque type addresses. This is expected to be done in:
|
opaque, ok := addr.(*lnwire.OpaqueAddrs)
|
||||||
// https://github.com/lightningnetwork/lnd/pull/9455.
|
if !ok {
|
||||||
// This TODO is being tracked in
|
addrs = append(addrs, addr)
|
||||||
// https://github.com/lightningnetwork/lnd/issues/9795 as this
|
continue
|
||||||
// must be addressed before making this code path active in
|
}
|
||||||
// production.
|
|
||||||
|
r := bytes.NewReader(opaque.Payload)
|
||||||
|
numAddrBytes := uint16(len(opaque.Payload))
|
||||||
|
byteRead, readAddr, err := lnwire.ReadAddress(
|
||||||
|
r, numAddrBytes,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
// We then just keep the address as opaque.
|
||||||
|
addrs = append(addrs, addr)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if readAddr != nil {
|
||||||
|
addrs = append(addrs, readAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if byteRead == numAddrBytes {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
addrs = append(addrs, &lnwire.OpaqueAddrs{
|
||||||
|
Payload: opaque.Payload[byteRead:],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(addrs) != 0 {
|
||||||
|
node.Addresses = addrs
|
||||||
|
}
|
||||||
|
|
||||||
// Write the node to the SQL database.
|
// Write the node to the SQL database.
|
||||||
id, err := upsertNode(ctx, sqlDB, node)
|
id, err := upsertNode(ctx, sqlDB, node)
|
||||||
|
@@ -124,6 +124,7 @@ func TestMigrateGraphToSQL(t *testing.T) {
|
|||||||
anotherAddr,
|
anotherAddr,
|
||||||
testOnionV2Addr,
|
testOnionV2Addr,
|
||||||
testOnionV3Addr,
|
testOnionV3Addr,
|
||||||
|
testDNSAddr,
|
||||||
testOpaqueAddr,
|
testOpaqueAddr,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
@@ -884,6 +885,100 @@ func TestSQLMigrationEdgeCases(t *testing.T) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("node with wrapped DNS address inside opaque addr",
|
||||||
|
func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Let the first node have an opaque address that we
|
||||||
|
// still don't understand. This node will remain the
|
||||||
|
// same in the SQL store.
|
||||||
|
n1 := makeTestNode(t, func(n *models.LightningNode) {
|
||||||
|
n.Addresses = []net.Addr{
|
||||||
|
testOpaqueAddr,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// The second node will have a wrapped DNS address
|
||||||
|
// inside an opaque address. The opaque address will
|
||||||
|
// only contain a DNS address and so the migrated node
|
||||||
|
// will only contain a DNS address and no opaque
|
||||||
|
// address.
|
||||||
|
n2 := makeTestNode(t, func(n *models.LightningNode) {
|
||||||
|
n.Addresses = []net.Addr{
|
||||||
|
testOpaqueAddrWithEmbeddedDNSAddr,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
n2Expected := *n2
|
||||||
|
n2Expected.Addresses = []net.Addr{
|
||||||
|
testDNSAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
// The third node will have an opaque address that
|
||||||
|
// wraps a DNS address along with some other data.
|
||||||
|
// So the resulting migrated node should have both
|
||||||
|
// the DNS address and remaining opaque address data.
|
||||||
|
n3 := makeTestNode(t, func(n *models.LightningNode) {
|
||||||
|
n.Addresses = []net.Addr{
|
||||||
|
testOpaqueAddrWithEmbeddedDNSAddrAndMore,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
n3Expected := *n3
|
||||||
|
n3Expected.Addresses = []net.Addr{
|
||||||
|
testDNSAddr,
|
||||||
|
testOpaqueAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
// The fourth node will have an opaque address that
|
||||||
|
// wraps an invalid DNS address. Such a node will be
|
||||||
|
// migrated, but we will keep the address as an opaque
|
||||||
|
// address in the SQL store.
|
||||||
|
n4 := makeTestNode(t, func(n *models.LightningNode) {
|
||||||
|
n.Addresses = []net.Addr{
|
||||||
|
testOpaqueAddrWithEmbeddedBadDNSAddr,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// The fifth node will have 2 DNS addresses embedded
|
||||||
|
// in the opaque address. The migration will result
|
||||||
|
// in the first dns address being extracted and the
|
||||||
|
// second one being left as an opaque address.
|
||||||
|
n5 := makeTestNode(t, func(n *models.LightningNode) {
|
||||||
|
n.Addresses = []net.Addr{
|
||||||
|
testOpaqueAddrWithTwoEmbeddedDNSAddrs,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
n5Expected := *n5
|
||||||
|
n5Expected.Addresses = []net.Addr{
|
||||||
|
testDNSAddr,
|
||||||
|
testOpaqueAddrWithEmbeddedDNSAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
populateKV := func(t *testing.T, db *KVStore) {
|
||||||
|
require.NoError(t, db.AddLightningNode(ctx, n1))
|
||||||
|
require.NoError(t, db.AddLightningNode(ctx, n2))
|
||||||
|
require.NoError(t, db.AddLightningNode(ctx, n3))
|
||||||
|
require.NoError(t, db.AddLightningNode(ctx, n4))
|
||||||
|
require.NoError(t, db.AddLightningNode(ctx, n5))
|
||||||
|
}
|
||||||
|
|
||||||
|
runTestMigration(t, populateKV, dbState{
|
||||||
|
nodes: []*models.LightningNode{
|
||||||
|
n1,
|
||||||
|
&n2Expected,
|
||||||
|
&n3Expected,
|
||||||
|
n4,
|
||||||
|
&n5Expected,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
// Here, we test that in the case where the KV store contains a channel
|
// Here, we test that in the case where the KV store contains a channel
|
||||||
// with invalid TLV data, the migration will still succeed, but the
|
// with invalid TLV data, the migration will still succeed, but the
|
||||||
// channel and its policies will not end up in the SQL store.
|
// channel and its policies will not end up in the SQL store.
|
||||||
@@ -1147,6 +1242,10 @@ type dbState struct {
|
|||||||
// assertResultState asserts that the SQLStore contains the expected
|
// assertResultState asserts that the SQLStore contains the expected
|
||||||
// state after a migration.
|
// state after a migration.
|
||||||
func assertResultState(t *testing.T, sql *SQLStore, expState dbState) {
|
func assertResultState(t *testing.T, sql *SQLStore, expState dbState) {
|
||||||
|
for _, node := range expState.nodes {
|
||||||
|
sortAddrs(node.Addresses)
|
||||||
|
}
|
||||||
|
|
||||||
// Assert that the sql store contains the expected nodes.
|
// Assert that the sql store contains the expected nodes.
|
||||||
require.ElementsMatch(t, expState.nodes, fetchAllNodes(t, sql))
|
require.ElementsMatch(t, expState.nodes, fetchAllNodes(t, sql))
|
||||||
require.ElementsMatch(
|
require.ElementsMatch(
|
||||||
|
338
lnwire/lnwire.go
338
lnwire/lnwire.go
@@ -719,9 +719,42 @@ func ReadElement(r io.Reader, element interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case *[]net.Addr:
|
case *[]net.Addr:
|
||||||
addresses, err := ReadAddresses(r)
|
// First, we'll read the number of total bytes that have been
|
||||||
if err != nil {
|
// used to encode the set of addresses.
|
||||||
return fmt.Errorf("unable to read addresses: %w", err)
|
var numAddrsBytes [2]byte
|
||||||
|
if _, err := io.ReadFull(r, numAddrsBytes[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
addrsLen := binary.BigEndian.Uint16(numAddrsBytes[:])
|
||||||
|
|
||||||
|
// With the number of addresses, read, we'll now pull in the
|
||||||
|
// buffer of the encoded addresses into memory.
|
||||||
|
addrs := make([]byte, addrsLen)
|
||||||
|
if _, err := io.ReadFull(r, addrs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
addrBuf := bytes.NewReader(addrs)
|
||||||
|
|
||||||
|
// Finally, we'll parse the remaining address payload in
|
||||||
|
// series, using the first byte to denote how to decode the
|
||||||
|
// address itself.
|
||||||
|
var (
|
||||||
|
addresses []net.Addr
|
||||||
|
addrBytesRead uint16
|
||||||
|
)
|
||||||
|
|
||||||
|
for addrBytesRead < addrsLen {
|
||||||
|
bytesRead, address, err := ReadAddress(
|
||||||
|
addrBuf, addrsLen-addrBytesRead,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to read address: %w",
|
||||||
|
err)
|
||||||
|
}
|
||||||
|
addrBytesRead += bytesRead
|
||||||
|
if address != nil {
|
||||||
|
addresses = append(addresses, address)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*e = addresses
|
*e = addresses
|
||||||
@@ -785,179 +818,148 @@ func ReadElements(r io.Reader, elements ...interface{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadAddresses reads encoded network addresses.
|
func ReadAddress(addrBuf io.Reader, addrsLen uint16) (uint16, net.Addr, error) {
|
||||||
//
|
var descriptor [1]byte
|
||||||
//nolint:funlen
|
if _, err := io.ReadFull(addrBuf, descriptor[:]); err != nil {
|
||||||
func ReadAddresses(r io.Reader) ([]net.Addr, error) {
|
return 0, nil, err
|
||||||
// First, we'll read the number of total bytes that have been
|
|
||||||
// used to encode the set of addresses.
|
|
||||||
var numAddrsBytes [2]byte
|
|
||||||
if _, err := io.ReadFull(r, numAddrsBytes[:]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
addrsLen := binary.BigEndian.Uint16(numAddrsBytes[:])
|
|
||||||
|
|
||||||
// With the number of addresses, read, we'll now pull in the
|
addrBytesRead := uint16(1)
|
||||||
// buffer of the encoded addresses into memory.
|
|
||||||
addrs := make([]byte, addrsLen)
|
|
||||||
if _, err := io.ReadFull(r, addrs); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
addrBuf := bytes.NewReader(addrs)
|
|
||||||
|
|
||||||
// Finally, we'll parse the remaining address payload in
|
var address net.Addr
|
||||||
// series, using the first byte to denote how to decode the
|
switch aType := addressType(descriptor[0]); aType {
|
||||||
// address itself.
|
case noAddr:
|
||||||
var (
|
return addrBytesRead, nil, nil
|
||||||
addresses []net.Addr
|
|
||||||
addrBytesRead uint16
|
|
||||||
)
|
|
||||||
|
|
||||||
for addrBytesRead < addrsLen {
|
case tcp4Addr:
|
||||||
var descriptor [1]byte
|
var ip [4]byte
|
||||||
if _, err := io.ReadFull(addrBuf, descriptor[:]); err != nil {
|
if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
|
||||||
return nil, err
|
return 0, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
addrBytesRead++
|
var port [2]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
|
||||||
var address net.Addr
|
return 0, nil, err
|
||||||
switch aType := addressType(descriptor[0]); aType {
|
|
||||||
case noAddr:
|
|
||||||
continue
|
|
||||||
|
|
||||||
case tcp4Addr:
|
|
||||||
var ip [4]byte
|
|
||||||
if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var port [2]byte
|
|
||||||
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
address = &net.TCPAddr{
|
|
||||||
IP: net.IP(ip[:]),
|
|
||||||
Port: int(binary.BigEndian.Uint16(port[:])),
|
|
||||||
}
|
|
||||||
addrBytesRead += tcp4AddrLen
|
|
||||||
|
|
||||||
case tcp6Addr:
|
|
||||||
var ip [16]byte
|
|
||||||
if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var port [2]byte
|
|
||||||
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
address = &net.TCPAddr{
|
|
||||||
IP: net.IP(ip[:]),
|
|
||||||
Port: int(binary.BigEndian.Uint16(port[:])),
|
|
||||||
}
|
|
||||||
addrBytesRead += tcp6AddrLen
|
|
||||||
|
|
||||||
case v2OnionAddr:
|
|
||||||
var h [tor.V2DecodedLen]byte
|
|
||||||
if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var p [2]byte
|
|
||||||
if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
onionService := tor.Base32Encoding.EncodeToString(h[:])
|
|
||||||
onionService += tor.OnionSuffix
|
|
||||||
port := int(binary.BigEndian.Uint16(p[:]))
|
|
||||||
|
|
||||||
address = &tor.OnionAddr{
|
|
||||||
OnionService: onionService,
|
|
||||||
Port: port,
|
|
||||||
}
|
|
||||||
addrBytesRead += v2OnionAddrLen
|
|
||||||
|
|
||||||
case v3OnionAddr:
|
|
||||||
var h [tor.V3DecodedLen]byte
|
|
||||||
if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var p [2]byte
|
|
||||||
if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
onionService := tor.Base32Encoding.EncodeToString(h[:])
|
|
||||||
onionService += tor.OnionSuffix
|
|
||||||
port := int(binary.BigEndian.Uint16(p[:]))
|
|
||||||
|
|
||||||
address = &tor.OnionAddr{
|
|
||||||
OnionService: onionService,
|
|
||||||
Port: port,
|
|
||||||
}
|
|
||||||
addrBytesRead += v3OnionAddrLen
|
|
||||||
|
|
||||||
case dnsAddr:
|
|
||||||
var hostnameLen [1]byte
|
|
||||||
_, err := io.ReadFull(addrBuf, hostnameLen[:])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
hostname := make([]byte, hostnameLen[0])
|
|
||||||
_, err = io.ReadFull(addrBuf, hostname)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var port [2]byte
|
|
||||||
_, err = io.ReadFull(addrBuf, port[:])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
address = &DNSAddress{
|
|
||||||
Hostname: string(hostname),
|
|
||||||
Port: binary.BigEndian.Uint16(
|
|
||||||
port[:],
|
|
||||||
),
|
|
||||||
}
|
|
||||||
addrBytesRead += dnsAddrOverhead +
|
|
||||||
uint16(len(hostname))
|
|
||||||
|
|
||||||
default:
|
|
||||||
// If we don't understand this address type,
|
|
||||||
// we just store it along with the remaining
|
|
||||||
// address bytes as type OpaqueAddrs. We need
|
|
||||||
// to hold onto the bytes so that we can still
|
|
||||||
// write them back to the wire when we
|
|
||||||
// propagate this message.
|
|
||||||
payloadLen := 1 + addrsLen - addrBytesRead
|
|
||||||
payload := make([]byte, payloadLen)
|
|
||||||
|
|
||||||
// First write a byte for the address type that
|
|
||||||
// we already read.
|
|
||||||
payload[0] = byte(aType)
|
|
||||||
|
|
||||||
// Now append the rest of the address bytes.
|
|
||||||
_, err := io.ReadFull(addrBuf, payload[1:])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
address = &OpaqueAddrs{
|
|
||||||
Payload: payload,
|
|
||||||
}
|
|
||||||
addrBytesRead = addrsLen
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addresses = append(addresses, address)
|
address = &net.TCPAddr{
|
||||||
|
IP: net.IP(ip[:]),
|
||||||
|
Port: int(binary.BigEndian.Uint16(port[:])),
|
||||||
|
}
|
||||||
|
addrBytesRead += tcp4AddrLen
|
||||||
|
|
||||||
|
case tcp6Addr:
|
||||||
|
var ip [16]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var port [2]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
address = &net.TCPAddr{
|
||||||
|
IP: net.IP(ip[:]),
|
||||||
|
Port: int(binary.BigEndian.Uint16(port[:])),
|
||||||
|
}
|
||||||
|
addrBytesRead += tcp6AddrLen
|
||||||
|
|
||||||
|
case v2OnionAddr:
|
||||||
|
var h [tor.V2DecodedLen]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var p [2]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
onionService := tor.Base32Encoding.EncodeToString(h[:])
|
||||||
|
onionService += tor.OnionSuffix
|
||||||
|
port := int(binary.BigEndian.Uint16(p[:]))
|
||||||
|
|
||||||
|
address = &tor.OnionAddr{
|
||||||
|
OnionService: onionService,
|
||||||
|
Port: port,
|
||||||
|
}
|
||||||
|
addrBytesRead += v2OnionAddrLen
|
||||||
|
|
||||||
|
case v3OnionAddr:
|
||||||
|
var h [tor.V3DecodedLen]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var p [2]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
onionService := tor.Base32Encoding.EncodeToString(h[:])
|
||||||
|
onionService += tor.OnionSuffix
|
||||||
|
port := int(binary.BigEndian.Uint16(p[:]))
|
||||||
|
|
||||||
|
address = &tor.OnionAddr{
|
||||||
|
OnionService: onionService,
|
||||||
|
Port: port,
|
||||||
|
}
|
||||||
|
addrBytesRead += v3OnionAddrLen
|
||||||
|
|
||||||
|
case dnsAddr:
|
||||||
|
var hostnameLen [1]byte
|
||||||
|
_, err := io.ReadFull(addrBuf, hostnameLen[:])
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
hostname := make([]byte, hostnameLen[0])
|
||||||
|
_, err = io.ReadFull(addrBuf, hostname)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var port [2]byte
|
||||||
|
_, err = io.ReadFull(addrBuf, port[:])
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
address = &DNSAddress{
|
||||||
|
Hostname: string(hostname),
|
||||||
|
Port: binary.BigEndian.Uint16(
|
||||||
|
port[:],
|
||||||
|
),
|
||||||
|
}
|
||||||
|
addrBytesRead += dnsAddrOverhead +
|
||||||
|
uint16(len(hostname))
|
||||||
|
|
||||||
|
default:
|
||||||
|
// If we don't understand this address type,
|
||||||
|
// we just store it along with the remaining
|
||||||
|
// address bytes as type OpaqueAddrs. We need
|
||||||
|
// to hold onto the bytes so that we can still
|
||||||
|
// write them back to the wire when we
|
||||||
|
// propagate this message.
|
||||||
|
payloadLen := 1 + addrsLen - addrBytesRead
|
||||||
|
payload := make([]byte, payloadLen)
|
||||||
|
|
||||||
|
// First write a byte for the address type that
|
||||||
|
// we already read.
|
||||||
|
payload[0] = byte(aType)
|
||||||
|
|
||||||
|
// Now append the rest of the address bytes.
|
||||||
|
_, err := io.ReadFull(addrBuf, payload[1:])
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
address = &OpaqueAddrs{
|
||||||
|
Payload: payload,
|
||||||
|
}
|
||||||
|
addrBytesRead = addrsLen
|
||||||
}
|
}
|
||||||
|
|
||||||
return addresses, nil
|
return addrBytesRead, address, nil
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user