@ -172,6 +172,10 @@ struct daemon {
/* @see lightningd.config.use_dns */
bool use_dns ;
/* The address that the broken response returns instead of
* NXDOMAIN . NULL if we have not detected a broken resolver . */
struct sockaddr * broken_resolver_response ;
} ;
/* Peers we're trying to reach. */
@ -360,6 +364,37 @@ new_local_peer_state(struct peer *peer, const struct crypto_state *cs)
return lps ;
}
/**
* Some ISP resolvers will reply with a dummy IP to queries that would otherwise
* result in an NXDOMAIN reply . This just checks whether we have one such
* resolver upstream and remembers its reply so we can try to filter future
* dummies out .
*/
static bool broken_resolver ( struct daemon * daemon )
{
struct addrinfo * addrinfo ;
struct addrinfo hints ;
char * hostname = " nxdomain-test.doesntexist " ;
int err ;
memset ( & hints , 0 , sizeof ( hints ) ) ;
hints . ai_family = AF_UNSPEC ;
hints . ai_socktype = SOCK_STREAM ;
hints . ai_protocol = 0 ;
hints . ai_flags = AI_ADDRCONFIG ;
err = getaddrinfo ( hostname , tal_fmt ( tmpctx , " %d " , 42 ) ,
& hints , & addrinfo ) ;
daemon - > broken_resolver_response =
tal_free ( daemon - > broken_resolver_response ) ;
if ( err = = 0 ) {
daemon - > broken_resolver_response = tal_dup ( daemon , struct sockaddr , addrinfo - > ai_addr ) ;
freeaddrinfo ( addrinfo ) ;
}
return daemon - > broken_resolver_response ! = NULL ;
}
static struct peer * new_peer ( const tal_t * ctx ,
struct daemon * daemon ,
const struct pubkey * their_id ,
@ -2855,6 +2890,11 @@ static struct io_plan *gossip_init(struct daemon_conn *master,
} else
daemon - > proxyaddr = NULL ;
if ( broken_resolver ( daemon ) ) {
status_trace ( " Broken DNS resolver detected, will check for "
" dummy replies " ) ;
}
/* Load stored gossip messages */
gossip_store_load ( daemon - > rstate , daemon - > rstate - > store ) ;
@ -3061,7 +3101,8 @@ static const char *seedname(const tal_t *ctx, const struct pubkey *id)
}
static struct wireaddr_internal *
seed_resolve_addr ( const tal_t * ctx , const struct pubkey * id )
seed_resolve_addr ( const tal_t * ctx , const struct pubkey * id ,
struct sockaddr * broken_reply )
{
struct wireaddr_internal * a ;
const char * addr ;
@ -3072,7 +3113,7 @@ seed_resolve_addr(const tal_t *ctx, const struct pubkey *id)
a = tal ( ctx , struct wireaddr_internal ) ;
a - > itype = ADDR_INTERNAL_WIREADDR ;
if ( ! wireaddr_from_hostname ( & a - > u . wireaddr , addr , DEFAULT_PORT , NULL ,
NULL ) ) {
broken_reply , NULL ) ) {
status_trace ( " Could not resolve %s " , addr ) ;
return tal_free ( a ) ;
} else {
@ -3170,7 +3211,8 @@ static void try_reach_peer(struct daemon *daemon, const struct pubkey *id,
wireaddr_from_unresolved ( a , seedname ( tmpctx , id ) ,
DEFAULT_PORT ) ;
} else if ( daemon - > use_dns ) {
a = seed_resolve_addr ( tmpctx , id ) ;
a = seed_resolve_addr ( tmpctx , id ,
daemon - > broken_resolver_response ) ;
}
}
@ -3685,6 +3727,7 @@ int main(int argc, char *argv[])
timers_init ( & daemon - > timers , time_mono ( ) ) ;
daemon - > broadcast_interval = 30000 ;
daemon - > last_announce_timestamp = 0 ;
daemon - > broken_resolver_response = NULL ;
/* stdin == control */
daemon_conn_init ( daemon , & daemon - > master , STDIN_FILENO , recv_req ,
master_gone ) ;