Skip to content

Commit 3260aea

Browse files
committed
dont assume socketaddr/ipaddr layout
1 parent 065d7c3 commit 3260aea

File tree

1 file changed

+31
-11
lines changed

1 file changed

+31
-11
lines changed

quinn-udp/src/unix.rs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::{
22
io,
33
io::IoSliceMut,
44
mem::{self, MaybeUninit},
5-
net::{IpAddr, SocketAddr},
5+
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
66
os::unix::io::AsRawFd,
77
ptr,
88
sync::atomic::AtomicUsize,
@@ -498,14 +498,16 @@ fn decode_recv(
498498
ecn_bits = cmsg::decode::<libc::c_int>(cmsg) as u8;
499499
}
500500
},
501-
(libc::IPPROTO_IP, libc::IP_PKTINFO) => unsafe {
502-
let pktinfo = cmsg::decode::<libc::in_pktinfo>(cmsg);
503-
dst_ip = Some(IpAddr::V4(ptr::read(&pktinfo.ipi_addr as *const _ as _)));
504-
},
505-
(libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => unsafe {
506-
let pktinfo = cmsg::decode::<libc::in6_pktinfo>(cmsg);
507-
dst_ip = Some(IpAddr::V6(ptr::read(&pktinfo.ipi6_addr as *const _ as _)));
508-
},
501+
(libc::IPPROTO_IP, libc::IP_PKTINFO) => {
502+
let pktinfo = unsafe { cmsg::decode::<libc::in_pktinfo>(cmsg) };
503+
dst_ip = Some(IpAddr::V4(Ipv4Addr::from(
504+
pktinfo.ipi_addr.s_addr.to_ne_bytes(),
505+
)));
506+
}
507+
(libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => {
508+
let pktinfo = unsafe { cmsg::decode::<libc::in6_pktinfo>(cmsg) };
509+
dst_ip = Some(IpAddr::V6(Ipv6Addr::from(pktinfo.ipi6_addr.s6_addr)));
510+
}
509511
#[cfg(target_os = "linux")]
510512
(libc::SOL_UDP, libc::UDP_GRO) => unsafe {
511513
stride = cmsg::decode::<libc::c_int>(cmsg) as usize;
@@ -515,8 +517,26 @@ fn decode_recv(
515517
}
516518

517519
let addr = match libc::c_int::from(name.ss_family) {
518-
libc::AF_INET => unsafe { SocketAddr::V4(ptr::read(&name as *const _ as _)) },
519-
libc::AF_INET6 => unsafe { SocketAddr::V6(ptr::read(&name as *const _ as _)) },
520+
libc::AF_INET => {
521+
// Safety: if the ss_family field is AF_INET then storage must be a sockaddr_in.
522+
let addr: &libc::sockaddr_in =
523+
unsafe { &*(&name as *const _ as *const libc::sockaddr_in) };
524+
SocketAddr::V4(SocketAddrV4::new(
525+
Ipv4Addr::from(addr.sin_addr.s_addr.to_ne_bytes()),
526+
u16::from_be(addr.sin_port),
527+
))
528+
}
529+
libc::AF_INET6 => {
530+
// Safety: if the ss_family field is AF_INET6 then storage must be a sockaddr_in6.
531+
let addr: &libc::sockaddr_in6 =
532+
unsafe { &*(&name as *const _ as *const libc::sockaddr_in6) };
533+
SocketAddr::V6(SocketAddrV6::new(
534+
Ipv6Addr::from(addr.sin6_addr.s6_addr),
535+
u16::from_be(addr.sin6_port),
536+
addr.sin6_flowinfo,
537+
addr.sin6_scope_id,
538+
))
539+
}
520540
_ => unreachable!(),
521541
};
522542

0 commit comments

Comments
 (0)