diff --git a/src/libstd/io/net/addrinfo.rs b/src/libstd/io/net/addrinfo.rs index 69ba64d856e..e8fbb121181 100644 --- a/src/libstd/io/net/addrinfo.rs +++ b/src/libstd/io/net/addrinfo.rs @@ -10,8 +10,8 @@ //! Synchronous DNS Resolution //! -//! Contains the functionality to perform DNS resolution in a style related to -//! `getaddrinfo()` +//! Contains the functionality to perform DNS resolution or reverse lookup, +//! in a style related to `getaddrinfo()` and `getnameinfo()`, respectively. #![allow(missing_docs)] @@ -24,6 +24,7 @@ use io::{IoResult}; use io::net::ip::{SocketAddr, IpAddr}; use option::Option; use option::Option::{Some, None}; +use string::String; use sys; use vec::Vec; @@ -83,6 +84,12 @@ pub fn get_host_addresses(host: &str) -> IoResult> { lookup(Some(host), None, None).map(|a| a.into_iter().map(|i| i.address.ip).collect()) } +/// Reverse name resolution. Given an address, returns the corresponding +/// hostname. +pub fn get_address_name(addr: IpAddr) -> IoResult { + sys::addrinfo::get_address_name(addr) +} + /// Full-fledged resolution. This function will perform a synchronous call to /// getaddrinfo, controlled by the parameters /// diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 24d22eb58c5..552d1c201da 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -13,6 +13,7 @@ use self::InAddr::*; use alloc::arc::Arc; use libc::{mod, c_char, c_int}; +use c_str::CString; use mem; use num::Int; use ptr::{mod, null, null_mut}; @@ -292,6 +293,43 @@ pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>, Ok(addrs) } +//////////////////////////////////////////////////////////////////////////////// +// get_address_name +//////////////////////////////////////////////////////////////////////////////// + +extern "system" { + fn getnameinfo(sa: *const libc::sockaddr, salen: libc::socklen_t, + host: *mut c_char, hostlen: libc::size_t, + serv: *mut c_char, servlen: libc::size_t, + flags: c_int) -> c_int; +} + +const NI_MAXHOST: uint = 1025; + +pub fn get_address_name(addr: IpAddr) -> Result { + let addr = SocketAddr{ip: addr, port: 0}; + + let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; + let len = addr_to_sockaddr(addr, &mut storage); + + let mut hostbuf = [0 as c_char, ..NI_MAXHOST]; + + let res = unsafe { + getnameinfo(&storage as *const _ as *const libc::sockaddr, len, + hostbuf.as_mut_ptr(), NI_MAXHOST as libc::size_t, + ptr::null_mut(), 0, + 0) + }; + + if res != 0 { + return Err(last_gai_error(res)); + } + + unsafe { + Ok(CString::new(hostbuf.as_ptr(), false).as_str().unwrap().to_string()) + } +} + //////////////////////////////////////////////////////////////////////////////// // Timeout helpers // diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 27fa7498673..dd4141de998 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -40,6 +40,7 @@ pub mod udp; pub mod addrinfo { pub use sys_common::net::get_host_addresses; + pub use sys_common::net::get_address_name; } // FIXME: move these to c module diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 15dc075cef9..3fae03146f3 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -41,6 +41,7 @@ pub mod udp; pub mod addrinfo { pub use sys_common::net::get_host_addresses; + pub use sys_common::net::get_address_name; } // FIXME: move these to c module