Skip to content

Commit 01c57c8

Browse files
multi: add dns_hostname_address field
1 parent 334a7d1 commit 01c57c8

File tree

9 files changed

+842
-27
lines changed

9 files changed

+842
-27
lines changed

config.go

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -330,26 +330,28 @@ type Config struct {
330330
// loadConfig function. We need to expose the 'raw' strings so the
331331
// command line library can access them.
332332
// Only the parsed net.Addrs should be used!
333-
RawRPCListeners []string `long:"rpclisten" description:"Add an interface/port/socket to listen for RPC connections"`
334-
RawRESTListeners []string `long:"restlisten" description:"Add an interface/port/socket to listen for REST connections"`
335-
RawListeners []string `long:"listen" description:"Add an interface/port to listen for peer connections"`
336-
RawExternalIPs []string `long:"externalip" description:"Add an ip:port to the list of local addresses we claim to listen on to peers. If a port is not specified, the default (9735) will be used regardless of other parameters"`
337-
ExternalHosts []string `long:"externalhosts" description:"Add a hostname:port that should be periodically resolved to announce IPs for. If a port is not specified, the default (9735) will be used."`
338-
RPCListeners []net.Addr
339-
RESTListeners []net.Addr
340-
RestCORS []string `long:"restcors" description:"Add an ip:port/hostname to allow cross origin access from. To allow all origins, set as \"*\"."`
341-
Listeners []net.Addr
342-
ExternalIPs []net.Addr
343-
DisableListen bool `long:"nolisten" description:"Disable listening for incoming peer connections"`
344-
DisableRest bool `long:"norest" description:"Disable REST API"`
345-
DisableRestTLS bool `long:"no-rest-tls" description:"Disable TLS for REST connections"`
346-
WSPingInterval time.Duration `long:"ws-ping-interval" description:"The ping interval for REST based WebSocket connections, set to 0 to disable sending ping messages from the server side"`
347-
WSPongWait time.Duration `long:"ws-pong-wait" description:"The time we wait for a pong response message on REST based WebSocket connections before the connection is closed as inactive"`
348-
NAT bool `long:"nat" description:"Toggle NAT traversal support (using either UPnP or NAT-PMP) to automatically advertise your external IP address to the network -- NOTE this does not support devices behind multiple NATs"`
349-
AddPeers []string `long:"addpeer" description:"Specify peers to connect to first"`
350-
MinBackoff time.Duration `long:"minbackoff" description:"Shortest backoff when reconnecting to persistent peers. Valid time units are {s, m, h}."`
351-
MaxBackoff time.Duration `long:"maxbackoff" description:"Longest backoff when reconnecting to persistent peers. Valid time units are {s, m, h}."`
352-
ConnectionTimeout time.Duration `long:"connectiontimeout" description:"The timeout value for network connections. Valid time units are {ms, s, m, h}."`
333+
RawRPCListeners []string `long:"rpclisten" description:"Add an interface/port/socket to listen for RPC connections"`
334+
RawRESTListeners []string `long:"restlisten" description:"Add an interface/port/socket to listen for REST connections"`
335+
RawListeners []string `long:"listen" description:"Add an interface/port to listen for peer connections"`
336+
RawExternalIPs []string `long:"externalip" description:"Add an ip:port to the list of local addresses we claim to listen on to peers. If a port is not specified, the default (9735) will be used regardless of other parameters"`
337+
RawExternalDNSHostnameAddress string `long:"external-dns-hostname" description:"Specify a DNS hostname for the node's external address. If no port is provided, the default (9735) is used."`
338+
ExternalHosts []string `long:"externalhosts" description:"Add a hostname:port that should be periodically resolved to announce IPs for. If a port is not specified, the default (9735) will be used."`
339+
RPCListeners []net.Addr
340+
RESTListeners []net.Addr
341+
RestCORS []string `long:"restcors" description:"Add an ip:port/hostname to allow cross origin access from. To allow all origins, set as \"*\"."`
342+
Listeners []net.Addr
343+
ExternalIPs []net.Addr
344+
ExternalDNSHostnameAddress *lnwire.DNSHostnameAddress
345+
DisableListen bool `long:"nolisten" description:"Disable listening for incoming peer connections"`
346+
DisableRest bool `long:"norest" description:"Disable REST API"`
347+
DisableRestTLS bool `long:"no-rest-tls" description:"Disable TLS for REST connections"`
348+
WSPingInterval time.Duration `long:"ws-ping-interval" description:"The ping interval for REST based WebSocket connections, set to 0 to disable sending ping messages from the server side"`
349+
WSPongWait time.Duration `long:"ws-pong-wait" description:"The time we wait for a pong response message on REST based WebSocket connections before the connection is closed as inactive"`
350+
NAT bool `long:"nat" description:"Toggle NAT traversal support (using either UPnP or NAT-PMP) to automatically advertise your external IP address to the network -- NOTE this does not support devices behind multiple NATs"`
351+
AddPeers []string `long:"addpeer" description:"Specify peers to connect to first"`
352+
MinBackoff time.Duration `long:"minbackoff" description:"Shortest backoff when reconnecting to persistent peers. Valid time units are {s, m, h}."`
353+
MaxBackoff time.Duration `long:"maxbackoff" description:"Longest backoff when reconnecting to persistent peers. Valid time units are {s, m, h}."`
354+
ConnectionTimeout time.Duration `long:"connectiontimeout" description:"The timeout value for network connections. Valid time units are {ms, s, m, h}."`
353355

354356
DebugLevel string `short:"d" long:"debuglevel" description:"Logging level for all subsystems {trace, debug, info, warn, error, critical} -- You may also specify <global-level>,<subsystem>=<level>,<subsystem2>=<level>,... to set the log level for individual subsystems -- Use show to list available subsystems"`
355357

@@ -1579,6 +1581,7 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser,
15791581
ltndLog.Infof("Listening on the p2p interface is disabled!")
15801582
cfg.Listeners = nil
15811583
cfg.ExternalIPs = nil
1584+
cfg.ExternalDNSHostnameAddress = nil
15821585
} else {
15831586

15841587
// Add default port to all listener addresses if needed and remove
@@ -1602,6 +1605,23 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser,
16021605
return nil, err
16031606
}
16041607

1608+
// Add default port to external dnsh hostname address if needed.
1609+
if cfg.RawExternalDNSHostnameAddress != "" {
1610+
addr, err := parseAddr(
1611+
cfg.RawExternalDNSHostnameAddress, cfg.net,
1612+
)
1613+
if err != nil {
1614+
return nil, err
1615+
}
1616+
dnsAddr, ok := addr.(*lnwire.DNSHostnameAddress)
1617+
if !ok {
1618+
return nil, fmt.Errorf("failed to cast "+
1619+
"address to lnwire.DNSHostnameAddr: "+
1620+
"got %T", addr)
1621+
}
1622+
cfg.ExternalDNSHostnameAddress = dnsAddr
1623+
}
1624+
16051625
// For the p2p port it makes no sense to listen to an Unix socket.
16061626
// Also, we would need to refactor the brontide listener to support
16071627
// that.

docs/release-notes/release-notes-0.20.0.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@
6363
# Technical and Architectural Updates
6464
## BOLT Spec Updates
6565

66+
* [Support DNS hostname address in
67+
Node Announcement message](https://github.com/lightningnetwork/lnd/pull/9455).
68+
See Bolt 07.
69+
6670
## Testing
6771

6872
## Database

graph/db/addr.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ const (
3131
// opaqueAddrs denotes an address (or a set of addresses) that LND was
3232
// not able to parse since LND is not yet aware of the address type.
3333
opaqueAddrs addressType = 4
34+
35+
// dnsHostnameAddr denotes a DNS hostname address.
36+
dnsHostnameAddr addressType = 5
3437
)
3538

3639
// encodeTCPAddr serializes a TCP address into its compact raw bytes
@@ -147,6 +150,50 @@ func encodeOpaqueAddrs(w io.Writer, addr *lnwire.OpaqueAddrs) error {
147150
return err
148151
}
149152

153+
// encodeDNSHostnameAddr serializes a DNS hostname address into its compact raw
154+
// bytes representation. It writes the address type, hostname length, hostname,
155+
// and port (in big-endian order) to the writer. The function validates that the
156+
// hostname is non-empty and does not exceed 255 characters complies with bolt 7
157+
// requirements. Returns an error if any part of the serialization fails.
158+
func encodeDNSHostnameAddr(w io.Writer, addr *lnwire.DNSHostnameAddress) error {
159+
// Ensure the hostname is not empty.
160+
if len(addr.Hostname) == 0 {
161+
return errors.New("hostname cannot be empty")
162+
}
163+
164+
// Ensure the hostname length complies with Bolt 7 requirements.
165+
// The maximum allowed length for a hostname is 255 characters.
166+
if len(addr.Hostname) > 255 {
167+
return fmt.Errorf("hostname length is %d, exceeds maximum "+
168+
"length of 255 characters", len(addr.Hostname))
169+
}
170+
171+
// Write the address type.
172+
if _, err := w.Write([]byte{byte(dnsHostnameAddr)}); err != nil {
173+
return err
174+
}
175+
176+
// Write the length of the hostname.
177+
hostnameLen := byte(len(addr.Hostname))
178+
if _, err := w.Write([]byte{hostnameLen}); err != nil {
179+
return err
180+
}
181+
182+
// Write the hostname bytes.
183+
if _, err := w.Write([]byte(addr.Hostname)); err != nil {
184+
return err
185+
}
186+
187+
// Write the port in big-endian order.
188+
var port [2]byte
189+
binary.BigEndian.PutUint16(port[:], uint16(addr.Port))
190+
if _, err := w.Write(port[:]); err != nil {
191+
return err
192+
}
193+
194+
return nil
195+
}
196+
150197
// DeserializeAddr reads the serialized raw representation of an address and
151198
// deserializes it into the actual address. This allows us to avoid address
152199
// resolution within the channeldb package.
@@ -247,6 +294,33 @@ func DeserializeAddr(r io.Reader) (net.Addr, error) {
247294
Payload: payload,
248295
}
249296

297+
case dnsHostnameAddr:
298+
var hostnameLen byte
299+
err := binary.Read(r, binary.BigEndian, &hostnameLen)
300+
if err != nil {
301+
return nil, err
302+
}
303+
304+
hostname := make([]byte, hostnameLen)
305+
if _, err := r.Read(hostname); err != nil {
306+
return nil, err
307+
}
308+
309+
var port [2]byte
310+
n, err := r.Read(port[:])
311+
if err != nil {
312+
return nil, err
313+
}
314+
if n != 2 {
315+
return nil, fmt.Errorf("expected to read 2 bytes for "+
316+
"port, but got %d bytes", n)
317+
}
318+
319+
address = &lnwire.DNSHostnameAddress{
320+
Hostname: string(hostname),
321+
Port: int(binary.BigEndian.Uint16(port[:])),
322+
}
323+
250324
default:
251325
return nil, ErrUnknownAddressType
252326
}
@@ -262,6 +336,8 @@ func SerializeAddr(w io.Writer, address net.Addr) error {
262336
return encodeTCPAddr(w, addr)
263337
case *tor.OnionAddr:
264338
return encodeOnionAddr(w, addr)
339+
case *lnwire.DNSHostnameAddress:
340+
return encodeDNSHostnameAddr(w, addr)
265341
case *lnwire.OpaqueAddrs:
266342
return encodeOpaqueAddrs(w, addr)
267343
default:

0 commit comments

Comments
 (0)