| 422 | } |
| 423 | |
| 424 | struct wireaddr * |
| 425 | wireaddr_from_hostname(const tal_t *ctx, |
| 426 | const char *hostname, |
| 427 | const u16 port, bool *no_dns, |
| 428 | struct sockaddr *broken_reply, |
| 429 | const char **err_msg) |
| 430 | { |
| 431 | struct wireaddr *addrs; |
| 432 | struct sockaddr_in6 *sa6; |
| 433 | struct sockaddr_in *sa4; |
| 434 | struct addrinfo *addrinfo, *addrinfos; |
| 435 | struct addrinfo hints; |
| 436 | int gai_err; |
| 437 | |
| 438 | addrs = tal_arr(ctx, struct wireaddr, 0); |
| 439 | if (no_dns) |
| 440 | *no_dns = false; |
| 441 | |
| 442 | /* Don't do lookup on onion addresses. */ |
| 443 | if (strends(hostname, ".onion")) { |
| 444 | u8 *dec = b32_decode(tmpctx, hostname, |
| 445 | strlen(hostname) - strlen(".onion")); |
| 446 | tal_resize(&addrs, 1); |
| 447 | if (tal_count(dec) == TOR_V3_ADDRLEN) { |
| 448 | addrs[0].type = ADDR_TYPE_TOR_V3; |
| 449 | } else { |
| 450 | if (err_msg) |
| 451 | *err_msg = "Invalid Tor address"; |
| 452 | return tal_free(addrs); |
| 453 | } |
| 454 | |
| 455 | addrs[0].addrlen = tal_count(dec); |
| 456 | addrs[0].port = port; |
| 457 | memcpy(addrs[0].addr, dec, tal_count(dec)); |
| 458 | return addrs; |
| 459 | } |
| 460 | |
| 461 | /* Tell them we wanted DNS and fail. */ |
| 462 | if (no_dns) { |
| 463 | if (err_msg) |
| 464 | *err_msg = "Needed DNS, but lookups suppressed"; |
| 465 | *no_dns = true; |
| 466 | return tal_free(addrs); |
| 467 | } |
| 468 | |
| 469 | memset(&hints, 0, sizeof(hints)); |
| 470 | hints.ai_family = AF_UNSPEC; |
| 471 | hints.ai_socktype = SOCK_STREAM; |
| 472 | hints.ai_protocol = 0; |
| 473 | hints.ai_flags = AI_ADDRCONFIG; |
| 474 | gai_err = getaddrinfo(hostname, tal_fmt(tmpctx, "%d", port), |
| 475 | &hints, &addrinfos); |
| 476 | if (gai_err != 0) { |
| 477 | if (err_msg) |
| 478 | *err_msg = gai_strerror(gai_err); |
| 479 | return tal_free(addrs); |
| 480 | } |
| 481 | |