{"record":{"id":"bb41ece716651975","repo":"shadowsocks/shadowsocks-rust","slug":"missing-destination-address-in-msghdr-bb41ec","errorCode":null,"errorMessage":"missing destination address in msghdr","messagePattern":"missing destination address in msghdr","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/shadowsocks-service/src/local/redir/udprelay/sys/unix/linux.rs","lineNumber":306,"sourceCode":"\n                        return Ok(());\n                    }\n                    (libc::SOL_IPV6, libc::IPV6_RECVORIGDSTADDR) => {\n                        ptr::copy(\n                            libc::CMSG_DATA(cmsg),\n                            dst_addr as *mut _,\n                            mem::size_of::<libc::sockaddr_in6>(),\n                        );\n                        *dst_addr_len = mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t;\n\n                        return Ok(());\n                    }\n                    _ => {}\n                }\n                cmsg = libc::CMSG_NXTHDR(msg, cmsg);\n            }\n\n            let err = Error::new(ErrorKind::InvalidData, \"missing destination address in msghdr\");\n            Err(err)\n        })?;\n\n        Ok(addr.as_socket().expect(\"SocketAddr\"))\n    }\n}\n\nfn recv_dest_from(socket: &UdpSocket, buf: &mut [u8]) -> io::Result<(usize, SocketAddr, SocketAddr)> {\n    unsafe {\n        let mut control_buf = [0u8; 64];\n        let mut src_addr: libc::sockaddr_storage = mem::zeroed();\n\n        let mut msg: libc::msghdr = mem::zeroed();\n        msg.msg_name = &mut src_addr as *mut _ as *mut _;\n        msg.msg_namelen = mem::size_of_val(&src_addr) as libc::socklen_t;\n\n        let mut iov = libc::iovec {\n            iov_base: buf.as_mut_ptr() as *mut _,","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/shadowsocks/shadowsocks-rust/blob/8eb0f0a65b1d976ab6bed5787327ef86529b0435/crates/shadowsocks-service/src/local/redir/udprelay/sys/unix/linux.rs#L288-L324","documentation":"Same as the FreeBSD variant: Linux tproxy UDP received a packet whose recvmsg control data did not include IP_ORIGDSTADDR/IPV6_ORIGDSTADDR, so the original destination could not be recovered and the packet is rejected with InvalidData.","triggerScenarios":"recv_dest_from on a Linux TProxy UDP socket when the kernel did not attach the original-destination cmsg — IP_TRANSPARENT set but the IP_RECVORIGDSTADDR socket option missing, or the packet arrived outside the TPROXY redirect path.","commonSituations":"Incomplete iptables TPROXY setup (missing mangle/PREROUTING rule), packets hitting the socket directly (e.g. tests binding and sending locally), or truncated control buffer.","solutions":["Ensure iptables/nftables TPROXY rules steer UDP packets to this socket so the kernel includes the original dst cmsg","Verify IP_RECVORIGDSTADDR (v4) and IPV6_RECVORIGDSTADDR (v6) were set on the socket before recvmsg","Provide a sufficiently large control-message buffer in recvmsg; truncation drops the cmsg","If testing locally, expect this error for packets not routed through the tproxy rules — route them or use a plain socket","Update to a version matching your kernel's cmsg support (IP_RECVORIGDSTADDR availability)"],"exampleFix":"// before: recvmsg without orig-dst option\n// after\nsocket.setsockopt(IPPROTO_IP, IP_RECVORIGDSTADDR, 1)?;\n// and iptables: -t mangle -A PREROUTING -p udp -j TPROXY --on-port 1080 --tproxy-mark 1","handlingStrategy":"validation","validationCode":"assert socket options IP_RECVORIGDSTADDR / IPV6_RECVORIGDSTADDR are set; verify `iptables -t mangle -L` contains TPROXY udp rule before starting the relay.","typeGuard":"fn has_origdst_cmsg(control: &[u8]) -> bool { control.iter().any(|c| is_origdst_cmsg(c)) }","tryCatchPattern":"if let Err(e) = sock.recv_dest_from(&mut buf).await { if e.kind()==InvalidData { metrics.drop_no_dst += 1; continue; } return Err(e); }","preventionTips":["Set both v4 and v6 orig-dst recv options","Ensure mangle/PREROUTING TPROXY rules with --tproxy-mark","Use control buffers >= 512 bytes","Check kernel supports IP_RECVORIGDSTADDR"],"tags":["network","udp","transparent-proxy","linux","tproxy"],"backgroundTag":"missing-required-argument","analyzedSha":"8eb0f0a65b1d976ab6bed5787327ef86529b0435","analyzedAt":"2026-09-09T12:20:43.168Z","contentChangedAt":"2026-09-09T12:20:43.168Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}