From 6d01a26510cd66aba61dea5e4988bc21d06496aa Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Tue, 29 Mar 2016 19:32:21 -0400 Subject: [PATCH] socket: Respect IPv6 flowinfo and scope_id in InetAddr::from_std Fixes #329 --- src/sys/socket/addr.rs | 26 ++++++++++++++++++++------ test/sys/test_socket.rs | 25 ++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs index 32210891ce..4854517f1e 100644 --- a/src/sys/socket/addr.rs +++ b/src/sys/socket/addr.rs @@ -36,12 +36,26 @@ pub enum InetAddr { impl InetAddr { pub fn from_std(std: &net::SocketAddr) -> InetAddr { - let ip = match *std { - net::SocketAddr::V4(ref addr) => IpAddr::V4(Ipv4Addr::from_std(&addr.ip())), - net::SocketAddr::V6(ref addr) => IpAddr::V6(Ipv6Addr::from_std(&addr.ip())), - }; - - InetAddr::new(ip, std.port()) + match *std { + net::SocketAddr::V4(ref addr) => { + InetAddr::V4(libc::sockaddr_in { + sin_family: AddressFamily::Inet as sa_family_t, + sin_port: addr.port().to_be(), // network byte order + sin_addr: Ipv4Addr::from_std(addr.ip()).0, + .. unsafe { mem::zeroed() } + }) + } + net::SocketAddr::V6(ref addr) => { + InetAddr::V6(libc::sockaddr_in6 { + sin6_family: AddressFamily::Inet6 as sa_family_t, + sin6_port: addr.port().to_be(), // network byte order + sin6_addr: Ipv6Addr::from_std(addr.ip()).0, + sin6_flowinfo: addr.flowinfo(), // host byte order + sin6_scope_id: addr.scope_id(), // host byte order + .. unsafe { mem::zeroed() } + }) + } + } } pub fn new(ip: IpAddr, port: u16) -> InetAddr { diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index ea6ef71ffe..bada112096 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -1,5 +1,6 @@ use nix::sys::socket::{InetAddr, UnixAddr, getsockname}; -use std::{mem, net}; +use std::mem; +use std::net::{self, Ipv6Addr, SocketAddr, SocketAddrV6}; use std::path::Path; use std::str::FromStr; use std::os::unix::io::{AsRawFd, RawFd}; @@ -28,6 +29,28 @@ pub fn test_inetv4_addr_to_sock_addr() { assert_eq!(actual, inet); } +#[test] +pub fn test_inetv6_addr_to_sock_addr() { + let port: u16 = 3000; + let flowinfo: u32 = 1; + let scope_id: u32 = 2; + let ip: Ipv6Addr = "fe80::1".parse().unwrap(); + + let actual = SocketAddr::V6(SocketAddrV6::new(ip, port, flowinfo, scope_id)); + let addr = InetAddr::from_std(&actual); + + match addr { + InetAddr::V6(addr) => { + assert_eq!(addr.sin6_port, port.to_be()); + assert_eq!(addr.sin6_flowinfo, flowinfo); + assert_eq!(addr.sin6_scope_id, scope_id); + } + _ => panic!("nope"), + } + + assert_eq!(actual, addr.to_std()); +} + #[test] pub fn test_path_to_sock_addr() { let actual = Path::new("/foo/bar");