{"record":{"id":"18dac760b8fa59d4","repo":"shadowsocks/shadowsocks-rust","slug":"missing-destination-address-in-msghdr-18dac7","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/openbsd.rs","lineNumber":307,"sourceCode":"                    }\n                    (libc::IPPROTO_IPV6, IPV6_RECVDSTPORT) => {\n                        let toaddr_in = &mut *(dst_addr as *mut libc::sockaddr_in6);\n                        ptr::copy_nonoverlapping(\n                            libc::CMSG_DATA(cmsg),\n                            &(*toaddr_in).sin6_port as *const _ as *mut _,\n                            mem::size_of::<libc::in_port_t>(),\n                        );\n                        if addr_or_port_received {\n                            return Ok(());\n                        } else {\n                            addr_or_port_received = true\n                        }\n                    }\n                    _ => {}\n                }\n                cmsg = libc::CMSG_NXTHDR(msg, cmsg);\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":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/shadowsocks/shadowsocks-rust/blob/8eb0f0a65b1d976ab6bed5787327ef86529b0435/crates/shadowsocks-service/src/local/redir/udprelay/sys/unix/openbsd.rs#L289-L325","documentation":"On OpenBSD, the UDP relay received a packet whose recvmsg ancillary data contained no original destination address, so get_destination_addr fails with InvalidData. The relay cannot know where to forward the packet without it.","triggerScenarios":"recv_dest_from when the expected cmsg (DIVERT or recv dst address) is absent — packet not diverted by pf with 'divert-to', or the socket option enabling destination reception was not set.","commonSituations":"pf rules missing 'divert-to' for UDP, packets arriving directly at the socket in tests, or control buffer too small causing cmsg truncation.","solutions":["Add/fix the pf rule using 'divert-to <port>' so UDP packets reach the socket with original destination preserved","Verify the socket enabled the destination-address receive option before recvmsg","Enlarge the cmsg control buffer to avoid MSG_CTRUNC dropping the address","Check that the packet actually traverses pf (route/anchor ordering)","Log cmsg content on failure to confirm whether the kernel provided any destination data"],"exampleFix":"// before: pass in via rdr-to only\npass in on $ext_if proto udp rdr-to 127.0.0.1 port 1080\n// after: preserve original dst\npass in on $ext_if proto udp divert-to 127.0.0.1 port 1080","handlingStrategy":"validation","validationCode":"// verify pf rule exists before starting relay\n// pfctl -sr | grep 'divert-to' must show a udp divert rule","typeGuard":"fn cmsg_carries_dst(control: &[u8]) -> bool { /* parse cmsg level/type for dst addr */ !control.is_empty() }","tryCatchPattern":"match relay.recv_dest_from(&mut buf).await { Err(e) if e.kind()==InvalidData => { log::warn!(\"no divert dst; check pf\"); continue; }, r => r? }","preventionTips":["Use 'divert-to' (not just rdr-to) for UDP in pf","Set the socket recv-dst option before recvmsg","Size the control buffer generously","Confirm packets traverse pf before reaching the socket"],"tags":["network","udp","transparent-proxy","openbsd","pf"],"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"}