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

  1. Ensure the firewall rule (e.g. pf 'rdr-to' with divert or ipfw fwd) actually preserves the original destination address for UDP packets
  2. Verify the socket enabled the recv-orig-dest-address socket option (IP_RECVDSTADDR / IPV6_RECVDSTADDR) before reading
  3. Confirm the selected RedirType is supported for UDP on FreeBSD; unsupported types create sockets without the needed options
  4. Check that the received control buffer (cmsg space) is large enough for the address cmsg; enlarge if truncated
  5. 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

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


AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09). Data as JSON: /api/errors/78c9112fc904296d. Report an issue: GitHub.