#![allow(dead_code)] // Copyright 2018 MaidSafe.net limited. // // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, // modified, or distributed except according to those terms. Please review the Licences for the // specific language governing permissions and limitations relating to use of the SAFE Network // Software. #[cfg(not(windows))] use libc::{sockaddr, sockaddr_in, sockaddr_in6, AF_INET, AF_INET6}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::ptr::NonNull; #[cfg(windows)] use winapi::{ shared::ws2def::{AF_INET, AF_INET6, SOCKADDR as sockaddr, SOCKADDR_IN as sockaddr_in}, shared::ws2ipdef::SOCKADDR_IN6 as sockaddr_in6, }; pub fn to_ipaddr(sockaddr: *const sockaddr) -> Option { if sockaddr.is_null() { return None; } SockAddr::new(sockaddr)?.as_ipaddr() } pub enum SockAddrIn { In(sockaddr_in), In6(sockaddr_in6), } // Wrapper around a sockaddr pointer. Guaranteed to not be null. pub struct SockAddr { inner: NonNull, } impl SockAddr { #[allow(clippy::new_ret_no_self)] pub fn new(sockaddr: *const sockaddr) -> Option { NonNull::new(sockaddr as *mut _).map(|inner| Self { inner }) } #[cfg(not(windows))] pub fn as_ipaddr(&self) -> Option { match self.sockaddr_in() { Some(SockAddrIn::In(sa)) => Some(IpAddr::V4(Ipv4Addr::new( ((sa.sin_addr.s_addr) & 255) as u8, ((sa.sin_addr.s_addr >> 8) & 255) as u8, ((sa.sin_addr.s_addr >> 16) & 255) as u8, ((sa.sin_addr.s_addr >> 24) & 255) as u8, ))), Some(SockAddrIn::In6(sa)) => Some(IpAddr::V6(Ipv6Addr::from(sa.sin6_addr.s6_addr))), None => None, } } #[cfg(windows)] pub fn as_ipaddr(&self) -> Option { match self.sockaddr_in() { Some(SockAddrIn::In(sa)) => { let s_addr = unsafe { sa.sin_addr.S_un.S_addr() }; Some(IpAddr::V4(Ipv4Addr::new( (s_addr & 255u32) as u8, ((s_addr >> 8) & 255u32) as u8, ((s_addr >> 16) & 255u32) as u8, ((s_addr >> 24) & 255u32) as u8, ))) } Some(SockAddrIn::In6(sa)) => { let s6_addr = unsafe { sa.sin6_addr.u.Byte() }; Some(IpAddr::V6(Ipv6Addr::from(*s6_addr))) } None => None, } } pub fn sockaddr_in(&self) -> Option { const AF_INET_U32: u32 = AF_INET as u32; const AF_INET6_U32: u32 = AF_INET6 as u32; match self.sa_family() { AF_INET_U32 => Some(SockAddrIn::In(self.sa_in())), AF_INET6_U32 => Some(SockAddrIn::In6(self.sa_in6())), _ => None, } } #[allow(unsafe_code)] pub fn sa_family(&self) -> u32 { unsafe { u32::from(self.inner.as_ref().sa_family) } } #[allow(unsafe_code)] #[allow(clippy::cast_ptr_alignment)] pub fn sa_in(&self) -> sockaddr_in { unsafe { *(self.inner.as_ptr() as *const sockaddr_in) } } #[allow(unsafe_code)] #[allow(clippy::cast_ptr_alignment)] pub fn sa_in6(&self) -> sockaddr_in6 { unsafe { *(self.inner.as_ptr() as *const sockaddr_in6) } } }