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