1 //! The BSD sockets API requires us to read the `ss_family` field before
2 //! we can interpret the rest of a `sockaddr` produced by the kernel.
3 #![allow(unsafe_code)]
4
5 use super::super::c;
6 use crate::io;
7 use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6};
8 use alloc::vec::Vec;
9 use core::mem::size_of;
10
11 // This must match the header of `sockaddr`.
12 #[repr(C)]
13 struct sockaddr_header {
14 ss_family: u16,
15 }
16
17 /// Read the `ss_family` field from a socket address returned from the OS.
18 ///
19 /// # Safety
20 ///
21 /// `storage` must point to a valid socket address returned from the OS.
22 #[inline]
read_ss_family(storage: *const c::sockaddr) -> u1623 unsafe fn read_ss_family(storage: *const c::sockaddr) -> u16 {
24 // Assert that we know the layout of `sockaddr`.
25 let _ = c::sockaddr {
26 __storage: c::sockaddr_storage {
27 __bindgen_anon_1: linux_raw_sys::general::__kernel_sockaddr_storage__bindgen_ty_1 {
28 __bindgen_anon_1:
29 linux_raw_sys::general::__kernel_sockaddr_storage__bindgen_ty_1__bindgen_ty_1 {
30 ss_family: 0_u16,
31 __data: [0; 126_usize],
32 },
33 },
34 },
35 };
36
37 (*storage.cast::<sockaddr_header>()).ss_family
38 }
39
40 /// Set the `ss_family` field of a socket address to `AF_UNSPEC`, so that we
41 /// can test for `AF_UNSPEC` to test whether it was stored to.
42 #[inline]
initialize_family_to_unspec(storage: *mut c::sockaddr)43 pub(crate) unsafe fn initialize_family_to_unspec(storage: *mut c::sockaddr) {
44 (*storage.cast::<sockaddr_header>()).ss_family = c::AF_UNSPEC as _;
45 }
46
47 /// Read a socket address encoded in a platform-specific format.
48 ///
49 /// # Safety
50 ///
51 /// `storage` must point to valid socket address storage.
read_sockaddr( storage: *const c::sockaddr, len: usize, ) -> io::Result<SocketAddrAny>52 pub(crate) unsafe fn read_sockaddr(
53 storage: *const c::sockaddr,
54 len: usize,
55 ) -> io::Result<SocketAddrAny> {
56 let offsetof_sun_path = super::addr::offsetof_sun_path();
57
58 if len < size_of::<c::sa_family_t>() {
59 return Err(io::Errno::INVAL);
60 }
61 match read_ss_family(storage).into() {
62 c::AF_INET => {
63 if len < size_of::<c::sockaddr_in>() {
64 return Err(io::Errno::INVAL);
65 }
66 let decode = *storage.cast::<c::sockaddr_in>();
67 Ok(SocketAddrAny::V4(SocketAddrV4::new(
68 Ipv4Addr::from(u32::from_be(decode.sin_addr.s_addr)),
69 u16::from_be(decode.sin_port),
70 )))
71 }
72 c::AF_INET6 => {
73 if len < size_of::<c::sockaddr_in6>() {
74 return Err(io::Errno::INVAL);
75 }
76 let decode = *storage.cast::<c::sockaddr_in6>();
77 Ok(SocketAddrAny::V6(SocketAddrV6::new(
78 Ipv6Addr::from(decode.sin6_addr.in6_u.u6_addr8),
79 u16::from_be(decode.sin6_port),
80 u32::from_be(decode.sin6_flowinfo),
81 decode.sin6_scope_id,
82 )))
83 }
84 c::AF_UNIX => {
85 if len < offsetof_sun_path {
86 return Err(io::Errno::INVAL);
87 }
88 if len == offsetof_sun_path {
89 Ok(SocketAddrAny::Unix(SocketAddrUnix::new(&[][..])?))
90 } else {
91 let decode = *storage.cast::<c::sockaddr_un>();
92 assert_eq!(
93 decode.sun_path[len - 1 - offsetof_sun_path],
94 b'\0' as c::c_char
95 );
96 Ok(SocketAddrAny::Unix(SocketAddrUnix::new(
97 decode.sun_path[..len - 1 - offsetof_sun_path]
98 .iter()
99 .map(|c| *c as u8)
100 .collect::<Vec<u8>>(),
101 )?))
102 }
103 }
104 _ => Err(io::Errno::NOTSUP),
105 }
106 }
107
108 /// Read a socket address returned from the OS.
109 ///
110 /// # Safety
111 ///
112 /// `storage` must point to a valid socket address returned from the OS.
maybe_read_sockaddr_os( storage: *const c::sockaddr, len: usize, ) -> Option<SocketAddrAny>113 pub(crate) unsafe fn maybe_read_sockaddr_os(
114 storage: *const c::sockaddr,
115 len: usize,
116 ) -> Option<SocketAddrAny> {
117 if len == 0 {
118 None
119 } else {
120 Some(read_sockaddr_os(storage, len))
121 }
122 }
123
124 /// Read a socket address returned from the OS.
125 ///
126 /// # Safety
127 ///
128 /// `storage` must point to a valid socket address returned from the OS.
read_sockaddr_os(storage: *const c::sockaddr, len: usize) -> SocketAddrAny129 pub(crate) unsafe fn read_sockaddr_os(storage: *const c::sockaddr, len: usize) -> SocketAddrAny {
130 let offsetof_sun_path = super::addr::offsetof_sun_path();
131
132 assert!(len >= size_of::<c::sa_family_t>());
133 match read_ss_family(storage).into() {
134 c::AF_INET => {
135 assert!(len >= size_of::<c::sockaddr_in>());
136 let decode = *storage.cast::<c::sockaddr_in>();
137 SocketAddrAny::V4(SocketAddrV4::new(
138 Ipv4Addr::from(u32::from_be(decode.sin_addr.s_addr)),
139 u16::from_be(decode.sin_port),
140 ))
141 }
142 c::AF_INET6 => {
143 assert!(len >= size_of::<c::sockaddr_in6>());
144 let decode = *storage.cast::<c::sockaddr_in6>();
145 SocketAddrAny::V6(SocketAddrV6::new(
146 Ipv6Addr::from(decode.sin6_addr.in6_u.u6_addr8),
147 u16::from_be(decode.sin6_port),
148 u32::from_be(decode.sin6_flowinfo),
149 decode.sin6_scope_id,
150 ))
151 }
152 c::AF_UNIX => {
153 assert!(len >= offsetof_sun_path);
154 if len == offsetof_sun_path {
155 SocketAddrAny::Unix(SocketAddrUnix::new(&[][..]).unwrap())
156 } else {
157 let decode = *storage.cast::<c::sockaddr_un>();
158 assert_eq!(
159 decode.sun_path[len - 1 - offsetof_sun_path],
160 b'\0' as c::c_char
161 );
162 SocketAddrAny::Unix(
163 SocketAddrUnix::new(
164 decode.sun_path[..len - 1 - offsetof_sun_path]
165 .iter()
166 .map(|c| *c as u8)
167 .collect::<Vec<u8>>(),
168 )
169 .unwrap(),
170 )
171 }
172 }
173 other => unimplemented!("{:?}", other),
174 }
175 }
176