| 2079 | /// Parse ancillary data from a received message header |
| 2080 | #[cfg(all(unix, not(target_os = "redox")))] |
| 2081 | fn parse_ancillary_data(msg: &libc::msghdr, vm: &VirtualMachine) -> PyResult<PyObjectRef> { |
| 2082 | let mut result = Vec::new(); |
| 2083 | |
| 2084 | // Calculate buffer end for truncation handling |
| 2085 | let ctrl_buf = msg.msg_control as *const u8; |
| 2086 | let ctrl_end = unsafe { ctrl_buf.add(msg.msg_controllen as _) }; |
| 2087 | |
| 2088 | let mut cmsg: *mut libc::cmsghdr = unsafe { libc::CMSG_FIRSTHDR(msg) }; |
| 2089 | while !cmsg.is_null() { |
| 2090 | let cmsg_ref = unsafe { &*cmsg }; |
| 2091 | let data_ptr = unsafe { libc::CMSG_DATA(cmsg) }; |
| 2092 | |
| 2093 | // Calculate data length, respecting buffer truncation |
| 2094 | let data_len_from_cmsg = |
| 2095 | cmsg_ref.cmsg_len as usize - (data_ptr as usize - cmsg as usize); |
| 2096 | let available = ctrl_end as usize - data_ptr as usize; |
| 2097 | let data_len = data_len_from_cmsg.min(available); |
| 2098 | |
| 2099 | let data = unsafe { core::slice::from_raw_parts(data_ptr, data_len) }; |
| 2100 | |
| 2101 | let tuple = vm.ctx.new_tuple(vec![ |
| 2102 | vm.ctx.new_int(cmsg_ref.cmsg_level).into(), |
| 2103 | vm.ctx.new_int(cmsg_ref.cmsg_type).into(), |
| 2104 | vm.ctx.new_bytes(data.to_vec()).into(), |
| 2105 | ]); |
| 2106 | |
| 2107 | result.push(tuple.into()); |
| 2108 | |
| 2109 | cmsg = unsafe { libc::CMSG_NXTHDR(msg, cmsg) }; |
| 2110 | } |
| 2111 | |
| 2112 | Ok(vm.ctx.new_list(result).into()) |
| 2113 | } |
| 2114 | |
| 2115 | // based on nix's implementation |
| 2116 | #[cfg(all(unix, not(target_os = "redox")))] |