connectd: hoist find_local_address so we can give more graceful Tor erros.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2022-03-03 20:56:11 +10:30
parent 200a8a985b
commit a62f5e5d82
3 changed files with 39 additions and 26 deletions

View file

@ -1227,6 +1227,31 @@ static int wireaddr_cmp_type(const struct wireaddr *a,
return cmp; return cmp;
} }
/* We need to have a bound address we can tell Tor to connect to */
static const struct wireaddr *
find_local_address(const struct wireaddr_internal *bindings)
{
for (size_t i = 0; i < tal_count(bindings); i++) {
if (bindings[i].itype != ADDR_INTERNAL_WIREADDR)
continue;
if (bindings[i].u.wireaddr.type != ADDR_TYPE_IPV4
&& bindings[i].u.wireaddr.type != ADDR_TYPE_IPV6)
continue;
return &bindings[i].u.wireaddr;
}
return NULL;
}
static bool want_tor(const struct wireaddr_internal *proposed_wireaddr)
{
for (size_t i = 0; i < tal_count(proposed_wireaddr); i++) {
if (proposed_wireaddr[i].itype == ADDR_INTERNAL_STATICTOR
|| proposed_wireaddr[i].itype == ADDR_INTERNAL_AUTOTOR)
return true;
}
return false;
}
/*~ The user can specify three kinds of addresses: ones we bind to but don't /*~ The user can specify three kinds of addresses: ones we bind to but don't
* announce, ones we announce but don't bind to, and ones we bind to and * announce, ones we announce but don't bind to, and ones we bind to and
* announce if they seem to be public addresses. * announce if they seem to be public addresses.
@ -1249,6 +1274,7 @@ static struct wireaddr_internal *setup_listeners(const tal_t *ctx,
struct sockaddr_un addrun; struct sockaddr_un addrun;
int fd; int fd;
struct wireaddr_internal *binding; struct wireaddr_internal *binding;
const struct wireaddr *localaddr;
const char *blob = NULL; const char *blob = NULL;
struct secret random; struct secret random;
struct pubkey pb; struct pubkey pb;
@ -1367,6 +1393,15 @@ static struct wireaddr_internal *setup_listeners(const tal_t *ctx,
proposed_wireaddr[i].itype); proposed_wireaddr[i].itype);
} }
/* Make sure we have at least one non-websocket address to send to,
* for Tor */
localaddr = find_local_address(binding);
if (want_tor(proposed_wireaddr) && !localaddr) {
*errstr = "Need to bind at least one local address,"
" to send Tor connections to";
return NULL;
}
/* If we want websockets to match IPv4/v6, set it up now. */ /* If we want websockets to match IPv4/v6, set it up now. */
if (daemon->websocket_port) { if (daemon->websocket_port) {
bool announced_some = false; bool announced_some = false;
@ -1417,7 +1452,7 @@ static struct wireaddr_internal *setup_listeners(const tal_t *ctx,
toraddr = tor_autoservice(tmpctx, toraddr = tor_autoservice(tmpctx,
&proposed_wireaddr[i], &proposed_wireaddr[i],
tor_password, tor_password,
binding, localaddr,
daemon->use_v3_autotor); daemon->use_v3_autotor);
if (!(proposed_listen_announce[i] & ADDR_ANNOUNCE)) { if (!(proposed_listen_announce[i] & ADDR_ANNOUNCE)) {
@ -1462,7 +1497,7 @@ static struct wireaddr_internal *setup_listeners(const tal_t *ctx,
&proposed_wireaddr[i], &proposed_wireaddr[i],
tor_password, tor_password,
blob, blob,
find_local_address(binding), localaddr,
0); 0);
/* get rid of blob data on our side of tor and add jitter */ /* get rid of blob data on our side of tor and add jitter */
randombytes_buf((void * const)proposed_wireaddr[i].u.torservice.blob, TOR_V3_BLOBLEN); randombytes_buf((void * const)proposed_wireaddr[i].u.torservice.blob, TOR_V3_BLOBLEN);

View file

@ -265,36 +265,18 @@ static void negotiate_auth(struct rbuf *rbuf, const char *tor_password)
"Tor protocolinfo did not give auth"); "Tor protocolinfo did not give auth");
} }
/* We need to have a bound address we can tell Tor to connect to */
const struct wireaddr *
find_local_address(const struct wireaddr_internal *bindings)
{
for (size_t i = 0; i < tal_count(bindings); i++) {
if (bindings[i].itype != ADDR_INTERNAL_WIREADDR)
continue;
if (bindings[i].u.wireaddr.type != ADDR_TYPE_IPV4
&& bindings[i].u.wireaddr.type != ADDR_TYPE_IPV6)
continue;
return &bindings[i].u.wireaddr;
}
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"No local address found to tell Tor to connect to");
}
struct wireaddr *tor_autoservice(const tal_t *ctx, struct wireaddr *tor_autoservice(const tal_t *ctx,
const struct wireaddr_internal *tor_serviceaddr, const struct wireaddr_internal *tor_serviceaddr,
const char *tor_password, const char *tor_password,
const struct wireaddr_internal *bindings, const struct wireaddr *laddr,
const bool use_v3_autotor) const bool use_v3_autotor)
{ {
int fd; int fd;
const struct wireaddr *laddr;
struct wireaddr *onion; struct wireaddr *onion;
struct addrinfo *ai_tor; struct addrinfo *ai_tor;
struct rbuf rbuf; struct rbuf rbuf;
char *buffer; char *buffer;
laddr = find_local_address(bindings);
ai_tor = wireaddr_to_addrinfo(tmpctx, &tor_serviceaddr->u.torservice.address); ai_tor = wireaddr_to_addrinfo(tmpctx, &tor_serviceaddr->u.torservice.address);
fd = socket(ai_tor->ai_family, SOCK_STREAM, 0); fd = socket(ai_tor->ai_family, SOCK_STREAM, 0);

View file

@ -9,7 +9,7 @@
struct wireaddr *tor_autoservice(const tal_t *ctx, struct wireaddr *tor_autoservice(const tal_t *ctx,
const struct wireaddr_internal *tor_serviceaddr, const struct wireaddr_internal *tor_serviceaddr,
const char *tor_password, const char *tor_password,
const struct wireaddr_internal *bindings, const struct wireaddr *localaddr,
const bool use_v3_autotor); const bool use_v3_autotor);
struct wireaddr *tor_fixed_service(const tal_t *ctx, struct wireaddr *tor_fixed_service(const tal_t *ctx,
@ -19,8 +19,4 @@ struct wireaddr *tor_fixed_service(const tal_t *ctx,
const struct wireaddr *bind, const struct wireaddr *bind,
const u8 index); const u8 index);
const struct wireaddr *
find_local_address(const struct wireaddr_internal *bindings);
#endif /* LIGHTNING_CONNECTD_TOR_AUTOSERVICE_H */ #endif /* LIGHTNING_CONNECTD_TOR_AUTOSERVICE_H */