shadowsocks/shadowsocks-rust · error
missing destination address in msghdr
Error message
missing destination address in msghdr
What it means
This error is thrown when a UDP transparent-proxy socket on FreeBSD receives a packet whose IP_RECVORIGDSTADDR/recvmsg control messages did not carry the original destination address. The relay needs that address to forward the packet, so without it the packet is dropped with InvalidData.
Source
Thrown at crates/shadowsocks-service/src/local/redir/udprelay/sys/unix/freebsd.rs:300
return Ok(());
}
(libc::IPPROTO_IPV6, libc::IPV6_ORIGDSTADDR) => {
ptr::copy_nonoverlapping(
libc::CMSG_DATA(cmsg),
dst_addr as *mut _,
mem::size_of::<libc::sockaddr_in6>(),
);
*dst_addr_len = mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t;
return Ok(());
}
_ => {}
}
cmsg = libc::CMSG_NXTHDR(msg, cmsg);
}
let err = Error::new(ErrorKind::InvalidData, "missing destination address in msghdr");
Err(err)
})?;
Ok(addr.as_socket().expect("SocketAddr"))
}
}
fn recv_dest_from(socket: &UdpSocket, buf: &mut [u8]) -> io::Result<(usize, SocketAddr, SocketAddr)> {
unsafe {
let mut control_buf = [0u8; 64];
let mut src_addr: libc::sockaddr_storage = mem::zeroed();
let mut msg: libc::msghdr = mem::zeroed();
msg.msg_name = &mut src_addr as *mut _ as *mut _;
msg.msg_namelen = mem::size_of_val(&src_addr) as libc::socklen_t;
let mut iov = libc::iovec {
iov_base: buf.as_mut_ptr() as *mut _,View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Ensure the firewall rule (e.g. pf 'rdr-to' with divert or ipfw fwd) actually preserves the original destination address for UDP packets
- Verify the socket enabled the recv-orig-dest-address socket option (IP_RECVDSTADDR / IPV6_RECVDSTADDR) before reading
- Confirm the selected RedirType is supported for UDP on FreeBSD; unsupported types create sockets without the needed options
- Check that the received control buffer (cmsg space) is large enough for the address cmsg; enlarge if truncated
- Log the raw cmsg when this occurs to see whether the kernel delivered any destination cmsg at all
Example fix
// before: socket created without orig-dst option let socket = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP))?; // after: enable receiving original destination socket.setsockopt(IPPROTO_IP, IP_RECVDSTADDR, 1)?; // + firewall divert-to rule
Defensive patterns
Strategy: validation
Validate before calling
// before binding, ensure options & firewall are set assert!(socket_has_orig_dst_option(&sock), "IP_RECVDSTADDR not enabled");
Type guard
fn has_dest_cmsg(cmsgs: &libc::msghdr) -> bool { !cmsgs.msg_controllen == 0 } // check a dst cmsg exists Try / catch
match relay.recv_dest_from(&mut buf).await { Err(e) if e.kind()==InvalidData => log::warn!("packet w/o orig dst dropped"), other => other? } Prevention
- Always set the recv-orig-destination socket option before recvmsg
- Verify pf/ipfw divert rules in deployment scripts
- Allocate a large cmsg control buffer
- Test with packets that traverse the firewall, not direct loopback sends
When it happens
Trigger: Calling recv_dest_from on a FreeBSD redir socket when the packet's cmsg data lacks the IP_ORIGDSTADDR/IPV6_ORIGDSTADDR control message — e.g. the socket was created as a plain UDP socket instead of a tproxy socket, or the IP_RECVDSTADDR/IP_RECVORIGDSTADDR socket option was not set.
Common situations: Running shadowsocks redirect/tproxy on FreeBSD with the firewall (pf/ipfw) not redirecting with the option that preserves the original destination, or a kernel/platform where the needed cmsg is stripped.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- redir destination must not be an domain name address
- not supported udp transparent proxy type
- not supported udp transparent proxy type
- missing destination address in msghdr
- not supported udp transparent proxy type
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/78c9112fc904296d.
Report an issue: GitHub.