mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 09:54:16 +01:00
bolt7: allow announcement of ADDR_TYPE_DNS
This commit is contained in:
parent
25bd09716f
commit
01e8a523e9
@ -281,6 +281,10 @@ void json_add_address(struct json_stream *response, const char *fieldname,
|
||||
json_add_string(response, "type", "torv3");
|
||||
json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr));
|
||||
json_add_num(response, "port", addr->port);
|
||||
} else if (addr->type == ADDR_TYPE_DNS) {
|
||||
json_add_string(response, "type", "dns");
|
||||
json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr));
|
||||
json_add_num(response, "port", addr->port);
|
||||
} else if (addr->type == ADDR_TYPE_WEBSOCKET) {
|
||||
json_add_string(response, "type", "websocket");
|
||||
json_add_num(response, "port", addr->port);
|
||||
|
@ -37,6 +37,11 @@ bool fromwire_wireaddr(const u8 **cursor, size_t *max, struct wireaddr *addr)
|
||||
case ADDR_TYPE_TOR_V3:
|
||||
addr->addrlen = TOR_V3_ADDRLEN;
|
||||
break;
|
||||
case ADDR_TYPE_DNS:
|
||||
addr->addrlen = fromwire_u8(cursor, max);
|
||||
memset(&addr->addr, 0, sizeof(addr->addr));
|
||||
addr->addr[addr->addrlen] = 0;
|
||||
break;
|
||||
case ADDR_TYPE_WEBSOCKET:
|
||||
addr->addrlen = 0;
|
||||
break;
|
||||
@ -52,6 +57,8 @@ bool fromwire_wireaddr(const u8 **cursor, size_t *max, struct wireaddr *addr)
|
||||
void towire_wireaddr(u8 **pptr, const struct wireaddr *addr)
|
||||
{
|
||||
towire_u8(pptr, addr->type);
|
||||
if (addr->type == ADDR_TYPE_DNS)
|
||||
towire_u8(pptr, addr->addrlen);
|
||||
towire(pptr, addr->addr, addr->addrlen);
|
||||
towire_u16(pptr, addr->port);
|
||||
}
|
||||
@ -211,6 +218,7 @@ bool wireaddr_is_wildcard(const struct wireaddr *addr)
|
||||
return memeqzero(addr->addr, addr->addrlen);
|
||||
case ADDR_TYPE_TOR_V2_REMOVED:
|
||||
case ADDR_TYPE_TOR_V3:
|
||||
case ADDR_TYPE_DNS:
|
||||
case ADDR_TYPE_WEBSOCKET:
|
||||
return false;
|
||||
}
|
||||
@ -259,6 +267,8 @@ char *fmt_wireaddr_without_port(const tal_t * ctx, const struct wireaddr *a)
|
||||
case ADDR_TYPE_TOR_V3:
|
||||
return tal_fmt(ctx, "%s.onion",
|
||||
b32_encode(tmpctx, a->addr, a->addrlen));
|
||||
case ADDR_TYPE_DNS:
|
||||
return tal_fmt(ctx, "%s", a->addr);
|
||||
case ADDR_TYPE_WEBSOCKET:
|
||||
return tal_strdup(ctx, "websocket");
|
||||
}
|
||||
@ -789,6 +799,7 @@ struct addrinfo *wireaddr_to_addrinfo(const tal_t *ctx,
|
||||
return ai;
|
||||
case ADDR_TYPE_TOR_V2_REMOVED:
|
||||
case ADDR_TYPE_TOR_V3:
|
||||
case ADDR_TYPE_DNS:
|
||||
case ADDR_TYPE_WEBSOCKET:
|
||||
break;
|
||||
}
|
||||
@ -841,6 +852,7 @@ bool all_tor_addresses(const struct wireaddr_internal *wireaddr)
|
||||
switch (wireaddr[i].u.wireaddr.type) {
|
||||
case ADDR_TYPE_IPV4:
|
||||
case ADDR_TYPE_IPV6:
|
||||
case ADDR_TYPE_DNS:
|
||||
return false;
|
||||
case ADDR_TYPE_TOR_V2_REMOVED:
|
||||
case ADDR_TYPE_TOR_V3:
|
||||
|
@ -37,13 +37,18 @@ struct sockaddr_un;
|
||||
* where `checksum = sha3(".onion checksum" | pubkey || version)[:2]`
|
||||
*/
|
||||
|
||||
/* BOLT-hostnames #7:
|
||||
* * `5`: DNS hostname; data = `[byte:len][len*byte:hostname][u16:port]` (length up to 258)
|
||||
*/
|
||||
|
||||
/* BOLT-websockets #7:
|
||||
* * `6`: WebSocket port; data = `[2:port]` (length 2)
|
||||
*/
|
||||
|
||||
#define TOR_V2_ADDRLEN 10
|
||||
#define TOR_V3_ADDRLEN 35
|
||||
#define LARGEST_ADDRLEN TOR_V3_ADDRLEN
|
||||
#define DNS_ADDRLEN 255
|
||||
#define LARGEST_ADDRLEN DNS_ADDRLEN
|
||||
#define TOR_V3_BLOBLEN 64
|
||||
#define STATIC_TOR_MAGIC_STRING "gen-default-toraddress"
|
||||
|
||||
@ -52,10 +57,10 @@ enum wire_addr_type {
|
||||
ADDR_TYPE_IPV6 = 2,
|
||||
ADDR_TYPE_TOR_V2_REMOVED = 3,
|
||||
ADDR_TYPE_TOR_V3 = 4,
|
||||
ADDR_TYPE_WEBSOCKET = 6,
|
||||
ADDR_TYPE_DNS = 5,
|
||||
ADDR_TYPE_WEBSOCKET = 6
|
||||
};
|
||||
|
||||
/* Structure now fit for tor support */
|
||||
struct wireaddr {
|
||||
enum wire_addr_type type;
|
||||
u8 addrlen;
|
||||
|
@ -975,6 +975,9 @@ static void try_connect_one_addr(struct connecting *connect)
|
||||
case ADDR_TYPE_IPV6:
|
||||
af = AF_INET6;
|
||||
break;
|
||||
case ADDR_TYPE_DNS:
|
||||
// TODO: resolve with getaddrinfo and set af
|
||||
break;
|
||||
case ADDR_TYPE_WEBSOCKET:
|
||||
af = -1;
|
||||
break;
|
||||
@ -1159,6 +1162,7 @@ static bool handle_wireaddr_listen(struct daemon *daemon,
|
||||
case ADDR_TYPE_WEBSOCKET:
|
||||
case ADDR_TYPE_TOR_V2_REMOVED:
|
||||
case ADDR_TYPE_TOR_V3:
|
||||
case ADDR_TYPE_DNS:
|
||||
break;
|
||||
}
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
@ -1614,6 +1618,8 @@ static void add_seed_addrs(struct wireaddr_internal **addrs,
|
||||
NULL, broken_reply, NULL);
|
||||
if (new_addrs) {
|
||||
for (size_t j = 0; j < tal_count(new_addrs); j++) {
|
||||
if (new_addrs[j].type == ADDR_TYPE_DNS)
|
||||
continue;
|
||||
struct wireaddr_internal a;
|
||||
a.itype = ADDR_INTERNAL_WIREADDR;
|
||||
a.u.wireaddr = new_addrs[j];
|
||||
|
@ -258,6 +258,7 @@ bool guess_address(struct wireaddr *addr)
|
||||
}
|
||||
case ADDR_TYPE_TOR_V2_REMOVED:
|
||||
case ADDR_TYPE_TOR_V3:
|
||||
case ADDR_TYPE_DNS:
|
||||
case ADDR_TYPE_WEBSOCKET:
|
||||
status_broken("Cannot guess address type %u", addr->type);
|
||||
break;
|
||||
|
@ -324,6 +324,9 @@ int main(int argc, char *argv[])
|
||||
case ADDR_TYPE_WEBSOCKET:
|
||||
opt_usage_exit_fail("Don't support websockets");
|
||||
break;
|
||||
case ADDR_TYPE_DNS:
|
||||
opt_usage_exit_fail("Don't support DNS");
|
||||
break;
|
||||
case ADDR_TYPE_IPV4:
|
||||
af = AF_INET;
|
||||
break;
|
||||
|
@ -40,10 +40,10 @@ On success, an object is returned, containing:
|
||||
- **network** (string): represents the type of network on the node are working (e.g: `bitcoin`, `testnet`, or `regtest`)
|
||||
- **fees_collected_msat** (msat): Total routing fees collected by this node
|
||||
- **address** (array of objects, optional): The addresses we announce to the world:
|
||||
- **type** (string): Type of connection (one of "ipv4", "ipv6", "torv2", "torv3", "websocket")
|
||||
- **type** (string): Type of connection (one of "dns", "ipv4", "ipv6", "torv2", "torv3", "websocket")
|
||||
- **port** (u16): port number
|
||||
|
||||
If **type** is "ipv4", "ipv6", "torv2" or "torv3":
|
||||
If **type** is "dns", "ipv4", "ipv6", "torv2" or "torv3":
|
||||
- **address** (string): address in expected format for **type**
|
||||
- **binding** (array of objects, optional): The addresses we are listening on:
|
||||
- **type** (string): Type of connection (one of "local socket", "ipv4", "ipv6", "torv2", "torv3")
|
||||
@ -117,4 +117,4 @@ RESOURCES
|
||||
---------
|
||||
|
||||
Main web site: <https://github.com/ElementsProject/lightning>
|
||||
[comment]: # ( SHA256STAMP:8374064ca0f95ab0c20d3edaf7f3742316af98f4d1e0e8de88922524f1ea3ce5)
|
||||
[comment]: # ( SHA256STAMP:90a3bacb6cb4456119afee8e60677c29bf5f46c4cd950e660a9f9c8e0433b473)
|
||||
|
@ -36,10 +36,10 @@ If **last_timestamp** is present:
|
||||
- **color** (hex): The favorite RGB color this node advertized (always 6 characters)
|
||||
- **features** (hex): BOLT #9 features bitmap this node advertized
|
||||
- **addresses** (array of objects): The addresses this node advertized:
|
||||
- **type** (string): Type of connection (one of "ipv4", "ipv6", "torv2", "torv3", "websocket")
|
||||
- **type** (string): Type of connection (one of "dns", "ipv4", "ipv6", "torv2", "torv3", "websocket")
|
||||
- **port** (u16): port number
|
||||
|
||||
If **type** is "ipv4", "ipv6", "torv2" or "torv3":
|
||||
If **type** is "dns", "ipv4", "ipv6", "torv2" or "torv3":
|
||||
- **address** (string): address in expected format for **type**
|
||||
|
||||
If **option_will_fund** is present:
|
||||
@ -52,9 +52,9 @@ If **option_will_fund** is present:
|
||||
- **compact_lease** (hex): the lease as represented in the node_announcement
|
||||
|
||||
[comment]: # (GENERATE-FROM-SCHEMA-END)
|
||||
|
||||
|
||||
On failure, one of the following error codes may be returned:
|
||||
|
||||
|
||||
- -32602: Error in given parameters.
|
||||
|
||||
EXAMPLE JSON RESPONSE
|
||||
@ -89,10 +89,10 @@ Vincenzo Palazzo <<vincenzo.palazzo@protonmail.com>> wrote the initial version o
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
FIXME:
|
||||
FIXME:
|
||||
|
||||
RESOURCES
|
||||
---------
|
||||
|
||||
Main web site: <https://github.com/ElementsProject/lightning>
|
||||
[comment]: # ( SHA256STAMP:4a5cfb1cf3d7fd77e49d6e7e369a9a6d374345b011d7db2fa9b4062156869ca4)
|
||||
[comment]: # ( SHA256STAMP:85400c9c1741943e2e02935b4f14fd187a7db6056410e42adec07ef3c6772f5f)
|
||||
|
@ -86,6 +86,7 @@
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"dns",
|
||||
"ipv4",
|
||||
"ipv6",
|
||||
"torv2",
|
||||
@ -104,6 +105,7 @@
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"dns",
|
||||
"ipv4",
|
||||
"ipv6",
|
||||
"torv2",
|
||||
|
@ -74,6 +74,7 @@
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"dns",
|
||||
"ipv4",
|
||||
"ipv6",
|
||||
"torv2",
|
||||
@ -92,6 +93,7 @@
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"dns",
|
||||
"ipv4",
|
||||
"ipv6",
|
||||
"torv2",
|
||||
|
@ -189,31 +189,52 @@ static char *opt_add_addr_withtype(const char *arg,
|
||||
char const *err_msg;
|
||||
struct wireaddr_internal wi;
|
||||
bool dns_ok;
|
||||
char *address;
|
||||
u16 port;
|
||||
|
||||
assert(arg != NULL);
|
||||
dns_ok = !ld->always_use_proxy && ld->config.use_dns;
|
||||
|
||||
if (!parse_wireaddr_internal(arg, &wi,
|
||||
ld->portnum,
|
||||
wildcard_ok, dns_ok, false,
|
||||
deprecated_apis, &err_msg)) {
|
||||
return tal_fmt(NULL, "Unable to parse address '%s': %s", arg, err_msg);
|
||||
if (!separate_address_and_port(tmpctx, arg, &address, &port))
|
||||
return tal_fmt(NULL, "Unable to parse address:port '%s'", arg);
|
||||
|
||||
if (is_ipaddr(address) || is_toraddr(address) || ala != ADDR_ANNOUNCE) {
|
||||
if (!parse_wireaddr_internal(arg, &wi, ld->portnum,
|
||||
wildcard_ok, dns_ok, false,
|
||||
deprecated_apis, &err_msg)) {
|
||||
return tal_fmt(NULL, "Unable to parse address '%s': %s", arg, err_msg);
|
||||
}
|
||||
|
||||
/* Sanity check for exact duplicates. */
|
||||
for (size_t i = 0; i < tal_count(ld->proposed_wireaddr); i++) {
|
||||
/* Only compare announce vs announce and bind vs bind */
|
||||
if ((ld->proposed_listen_announce[i] & ala) == 0)
|
||||
continue;
|
||||
|
||||
if (wireaddr_internal_eq(&ld->proposed_wireaddr[i], &wi))
|
||||
return tal_fmt(NULL, "Duplicate %s address %s",
|
||||
ala & ADDR_ANNOUNCE ? "announce" : "listen",
|
||||
type_to_string(tmpctx, struct wireaddr_internal, &wi));
|
||||
}
|
||||
|
||||
tal_arr_expand(&ld->proposed_listen_announce, ala);
|
||||
tal_arr_expand(&ld->proposed_wireaddr, wi);
|
||||
}
|
||||
|
||||
/* Sanity check for exact duplicates. */
|
||||
for (size_t i = 0; i < tal_count(ld->proposed_wireaddr); i++) {
|
||||
/* Only compare announce vs announce and bind vs bind */
|
||||
if ((ld->proposed_listen_announce[i] & ala) == 0)
|
||||
continue;
|
||||
/* Add ADDR_TYPE_DNS to announce DNS hostnames */
|
||||
if (is_dnsaddr(address) && ala & ADDR_ANNOUNCE) {
|
||||
memset(&wi, 0, sizeof(wi));
|
||||
wi.itype = ADDR_INTERNAL_WIREADDR;
|
||||
wi.u.wireaddr.type = ADDR_TYPE_DNS;
|
||||
wi.u.wireaddr.addrlen = strlen(address);
|
||||
strncpy((char * restrict)&wi.u.wireaddr.addr,
|
||||
address, sizeof(wi.u.wireaddr.addr) - 1);
|
||||
wi.u.wireaddr.port = port;
|
||||
|
||||
if (wireaddr_internal_eq(&ld->proposed_wireaddr[i], &wi))
|
||||
return tal_fmt(NULL, "Duplicate %s address %s",
|
||||
ala & ADDR_ANNOUNCE ? "announce" : "listen",
|
||||
type_to_string(tmpctx, struct wireaddr_internal, &wi));
|
||||
tal_arr_expand(&ld->proposed_listen_announce, ADDR_ANNOUNCE);
|
||||
tal_arr_expand(&ld->proposed_wireaddr, wi);
|
||||
}
|
||||
|
||||
tal_arr_expand(&ld->proposed_listen_announce, ala);
|
||||
tal_arr_expand(&ld->proposed_wireaddr, wi);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
@ -110,9 +110,11 @@ def test_announce_address(node_factory, bitcoind):
|
||||
"""Make sure our announcements are well formed."""
|
||||
|
||||
# We do not allow announcement of duplicates.
|
||||
opts = {'announce-addr':
|
||||
opts = {'disable-dns': None, 'announce-addr':
|
||||
['4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad.onion',
|
||||
'1.2.3.4:1234',
|
||||
'localhost:1235',
|
||||
'example.com:1236',
|
||||
'::'],
|
||||
'log-level': 'io',
|
||||
'dev-allow-localhost': None}
|
||||
@ -126,12 +128,30 @@ def test_announce_address(node_factory, bitcoind):
|
||||
l2.wait_channel_active(scid)
|
||||
|
||||
# We should see it send node announce with all addresses (257 = 0x0101)
|
||||
# local ephemeral port is masked out.
|
||||
l1.daemon.wait_for_log(r"\[OUT\] 0101.*47"
|
||||
"010102030404d2"
|
||||
"017f000001...."
|
||||
"02000000000000000000000000000000002607"
|
||||
"04e00533f3e8f2aedaa8969b3d0fa03a96e857bbb28064dca5e147e934244b9ba50230032607")
|
||||
# Note: local ephemeral port is masked out.
|
||||
# Note: Since we `disable-dns` it should not announce a resolved IPv4
|
||||
# or IPv6 address for example.com
|
||||
#
|
||||
# Also expect the address descriptor types to be sorted!
|
||||
# BOLT #7:
|
||||
# - MUST place address descriptors in ascending order.
|
||||
l1.daemon.wait_for_log(r"\[OUT\] 0101.*0063"
|
||||
"010102030404d2" # IPv4 01 1.2.3.4:1234
|
||||
"017f000001...." # IPv4 01 127.0.0.1:wxyz
|
||||
"02000000000000000000000000000000002607" # IPv6 02 :::9735
|
||||
"04e00533f3e8f2aedaa8969b3d0fa03a96e857bbb28064dca5e147e934244b9ba50230032607" # TORv3 04
|
||||
"05096c6f63616c686f737404d3" # DNS 05 len localhost:1235
|
||||
"050b6578616d706c652e636f6d04d4") # DNS 05 len example.com:1236
|
||||
|
||||
# Check other node can parse these
|
||||
addresses = l2.rpc.listnodes(l1.info['id'])['nodes'][0]['addresses']
|
||||
addresses_dns = [address for address in addresses if address['type'] == 'dns']
|
||||
assert len(addresses) == 6
|
||||
assert len(addresses_dns) == 2
|
||||
assert addresses_dns[0]['address'] == 'localhost'
|
||||
assert addresses_dns[0]['port'] == 1235
|
||||
assert addresses_dns[1]['address'] == 'example.com'
|
||||
assert addresses_dns[1]['port'] == 1236
|
||||
|
||||
|
||||
@pytest.mark.developer("needs DEVELOPER=1")
|
||||
|
Loading…
Reference in New Issue
Block a user