]> git.lizzy.rs Git - rust.git/commitdiff
Add `std::net::lookup_addr` for reverse DNS lookup
authorMurarth <murarth@gmail.com>
Mon, 16 Mar 2015 20:04:31 +0000 (13:04 -0700)
committerMurarth <murarth@gmail.com>
Fri, 27 Mar 2015 00:13:14 +0000 (17:13 -0700)
Closes #22608

src/libstd/net/addr.rs
src/libstd/net/mod.rs
src/libstd/sys/common/net2.rs

index dafca974bec0eacf96d39c766cb466fa68024996..a08b33b342bece06aebe3183e2646b9301a2d70b 100644 (file)
@@ -47,6 +47,15 @@ pub struct SocketAddrV4 { inner: libc::sockaddr_in }
 pub struct SocketAddrV6 { inner: libc::sockaddr_in6 }
 
 impl SocketAddr {
+    /// Creates a new socket address from the (ip, port) pair.
+    #[unstable(feature = "ip_addr", reason = "recent addition")]
+    pub fn new(ip: IpAddr, port: u16) -> SocketAddr {
+        match ip {
+            IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)),
+            IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)),
+        }
+    }
+
     /// Gets the IP address associated with this socket address.
     #[unstable(feature = "ip_addr", reason = "recent addition")]
     pub fn ip(&self) -> IpAddr {
index 7f51b1cba3fe796a8ef66bd4aab1ac06f792525f..68f3098d993c0510af6d2687bcb9d26a95c5841e 100644 (file)
@@ -111,3 +111,13 @@ fn next(&mut self) -> Option<io::Result<SocketAddr>> { self.0.next() }
 pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
     net_imp::lookup_host(host).map(LookupHost)
 }
+
+/// Resolve the given address to a hostname.
+///
+/// This function may perform a DNS query to resolve `addr` and may also inspect
+/// system configuration to resolve the specified address. If the address
+/// cannot be resolved, it is returned in string format.
+#[unstable(feature = "lookup_addr", reason = "recent addition")]
+pub fn lookup_addr(addr: &IpAddr) -> io::Result<String> {
+    net_imp::lookup_addr(addr)
+}
index e213a86644fe1ee5fd7f14e976b53874def7342f..a8ee40639e32ee3fcda50ff9acdd78c0ef6290ba 100644 (file)
 
 use prelude::v1::*;
 
-use ffi::CString;
+use ffi::{CStr, CString};
 use io::{self, Error, ErrorKind};
 use libc::{self, c_int, c_char, c_void, socklen_t};
 use mem;
 use net::{SocketAddr, Shutdown, IpAddr};
+use str::from_utf8;
 use sys::c;
 use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t};
 use sys_common::{AsInner, FromInner, IntoInner};
@@ -126,6 +127,42 @@ pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// lookup_addr
+////////////////////////////////////////////////////////////////////////////////
+
+extern "system" {
+    fn getnameinfo(sa: *const libc::sockaddr, salen: 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: usize = 1025;
+
+pub fn lookup_addr(addr: &IpAddr) -> io::Result<String> {
+    init();
+
+    let saddr = SocketAddr::new(*addr, 0);
+    let (inner, len) = saddr.into_inner();
+    let mut hostbuf = [0 as c_char; NI_MAXHOST];
+
+    let data = unsafe {
+        try!(cvt_gai(getnameinfo(inner, len,
+                                 hostbuf.as_mut_ptr(), NI_MAXHOST as libc::size_t,
+                                 0 as *mut _, 0, 0)));
+
+        CStr::from_ptr(hostbuf.as_ptr())
+    };
+
+    match from_utf8(data.to_bytes()) {
+        Ok(name) => Ok(name.to_string()),
+        Err(_) => Err(io::Error::new(io::ErrorKind::Other,
+                                     "failed to lookup address information",
+                                     Some("invalid host name".to_string())))
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // TCP streams
 ////////////////////////////////////////////////////////////////////////////////