]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #34700 - inejge:ai-hints, r=alexcrichton
authorManish Goregaokar <manishsmail@gmail.com>
Fri, 8 Jul 2016 07:44:21 +0000 (13:14 +0530)
committerManish Goregaokar <manishsmail@gmail.com>
Fri, 8 Jul 2016 09:17:00 +0000 (14:47 +0530)
Use hints with getaddrinfo() in std::net::lookup_host()

As noted in #24250, `std::net::lookup_host()` repeats each IPv[46] address in the result set. The number of repetitions is OS-dependent; e.g., Linux and FreeBSD give three copies, OpenBSD gives two. Filtering the duplicates can be done by the user if `lookup_host()` is used explicitly, but not with functions like `TcpStream::connect()`. What happens with the latter is that any unsuccessful connection attempt will be repeated as many times as there are duplicates of the address.

The program:

```rust
use std::net::TcpStream;

fn main() {
    let _stream = TcpStream::connect("localhost:4444").unwrap();
}
```

results in the following capture:

[capture-before.txt](https://github.com/rust-lang/rust/files/352004/capture-before.txt)

assuming that "localhost" resolves both to ::1 and 127.0.0.1, and that the listening program opens just an IPv4 socket (e.g., `nc -l 127.0.0.1 4444`.) The reason for this behavior is explained in [this comment](https://github.com/rust-lang/rust/issues/24250#issuecomment-92240152): `getaddrinfo()` is not constrained.

Various OSS projects (I checked out Postfix, OpenLDAP, Apache HTTPD and BIND) which use `getaddrinfo()` generally constrain the result set by using a non-NULL `hints` parameter and setting at least `ai_socktype` to `SOCK_STREAM`. `SOCK_DGRAM` would also work. Other parameters are unnecessary for pure name resolution.

The patch in this PR initializes a `hints` struct and passes it to `getaddrinfo()`, which eliminates the duplicates. The same test program as above with this change produces:

[capture-after.txt](https://github.com/rust-lang/rust/files/352042/capture-after.txt)

All `libstd` tests pass with this patch.

src/libstd/sys/common/net.rs

index 274e495d70eb620b3f0d4e5f2ea91ee618825dfb..26925b12f93d6ba3d28fb0fb0eee80c1f8d639c0 100644 (file)
@@ -152,9 +152,19 @@ pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
     init();
 
     let c_host = CString::new(host)?;
+    let hints = c::addrinfo {
+        ai_flags: 0,
+        ai_family: 0,
+        ai_socktype: c::SOCK_STREAM,
+        ai_protocol: 0,
+        ai_addrlen: 0,
+        ai_addr: ptr::null_mut(),
+        ai_canonname: ptr::null_mut(),
+        ai_next: ptr::null_mut()
+    };
     let mut res = ptr::null_mut();
     unsafe {
-        cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), ptr::null(),
+        cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints,
                                &mut res))?;
         Ok(LookupHost { original: res, cur: res })
     }