1use std::io;
2use std::net::IpAddr;
3use std::str;
4
5#[cfg(unix)]
6use libc::{NI_NAMEREQD, NI_NUMERICSERV, SOCK_STREAM};
7
8#[cfg(windows)]
9use windows_sys::Win32::Networking::WinSock::{NI_NAMEREQD, NI_NUMERICSERV, SOCK_STREAM};
10
11use crate::addrinfo::{getaddrinfo, AddrInfoHints};
12use crate::nameinfo::getnameinfo;
13
14pub fn lookup_host(host: &str) -> io::Result<Vec<IpAddr>> {
18 let hints = AddrInfoHints {
19 socktype: SOCK_STREAM as i32,
20 ..AddrInfoHints::default()
21 };
22
23 match getaddrinfo(Some(host), None, Some(hints)) {
24 Ok(addrs) => {
25 let addrs: io::Result<Vec<_>> = addrs.map(|r| r.map(|a| a.sockaddr.ip())).collect();
26 addrs
27 }
28 Err(e) => {
29 reload_dns_nameserver();
30 Err(e)?
31 }
32 }
33}
34
35pub fn lookup_addr(addr: &IpAddr) -> io::Result<String> {
39 let sock = (*addr, 0).into();
40 match getnameinfo(&sock, (NI_NUMERICSERV | NI_NAMEREQD) as i32) {
41 Ok((name, _)) => Ok(name),
42 Err(e) => {
43 reload_dns_nameserver();
44 Err(e)?
45 }
46 }
47}
48
49fn reload_dns_nameserver() {
54 cfg_if::cfg_if! {
55 if #[cfg(target_os = "macos")] {
56 } else if #[cfg(target_os = "ios")] {
57 } else if #[cfg(target_os = "tvos")] {
58 } else if #[cfg(unix)] {
59 use libc;
60 unsafe {
61 libc::res_init();
62 }
63 }
64 }
65}
66
67#[test]
68fn test_localhost() {
69 let ips = lookup_host("localhost").unwrap();
70 assert!(ips.contains(&IpAddr::V4("127.0.0.1".parse().unwrap())));
71 assert!(!ips.contains(&IpAddr::V4("10.0.0.1".parse().unwrap())));
72}
73
74#[cfg(unix)]
75#[test]
76fn test_rev_localhost() {
77 let name = lookup_addr(&IpAddr::V4("127.0.0.1".parse().unwrap()));
78 assert_eq!(name.unwrap(), "localhost");
79}
80
81#[cfg(windows)]
82#[test]
83fn test_hostname() {
84 let hostname = crate::hostname::get_hostname().unwrap();
86
87 let rev_name = lookup_addr(&IpAddr::V4("127.0.0.1".parse().unwrap()));
89
90 assert_eq!(rev_name.unwrap(), hostname);
91}