| 1876 | #[cfg(target_os = "linux")] |
| 1877 | #[pymethod] |
| 1878 | fn sendmsg_afalg(&self, args: SendmsgAfalgArgs, vm: &VirtualMachine) -> PyResult<usize> { |
| 1879 | let msg = args.msg; |
| 1880 | let op = args.op; |
| 1881 | let iv = args.iv; |
| 1882 | let flags = args.flags; |
| 1883 | |
| 1884 | // Validate assoclen - must be non-negative if provided |
| 1885 | let assoclen: Option<u32> = match args.assoclen { |
| 1886 | OptionalArg::Present(val) if val < 0 => { |
| 1887 | return Err(vm.new_type_error("assoclen must be non-negative")); |
| 1888 | } |
| 1889 | OptionalArg::Present(val) => Some(val as u32), |
| 1890 | OptionalArg::Missing => None, |
| 1891 | }; |
| 1892 | |
| 1893 | // Build control messages for AF_ALG |
| 1894 | let mut control_buf = Vec::new(); |
| 1895 | |
| 1896 | // Add ALG_SET_OP control message |
| 1897 | { |
| 1898 | let op_bytes = op.to_ne_bytes(); |
| 1899 | let space = |
| 1900 | unsafe { libc::CMSG_SPACE(core::mem::size_of::<u32>() as u32) } as usize; |
| 1901 | let old_len = control_buf.len(); |
| 1902 | control_buf.resize(old_len + space, 0u8); |
| 1903 | |
| 1904 | let cmsg = control_buf[old_len..].as_mut_ptr() as *mut libc::cmsghdr; |
| 1905 | unsafe { |
| 1906 | (*cmsg).cmsg_len = libc::CMSG_LEN(core::mem::size_of::<u32>() as u32) as _; |
| 1907 | (*cmsg).cmsg_level = libc::SOL_ALG; |
| 1908 | (*cmsg).cmsg_type = libc::ALG_SET_OP; |
| 1909 | let data = libc::CMSG_DATA(cmsg); |
| 1910 | core::ptr::copy_nonoverlapping(op_bytes.as_ptr(), data, op_bytes.len()); |
| 1911 | } |
| 1912 | } |
| 1913 | |
| 1914 | // Add ALG_SET_IV control message if iv is provided |
| 1915 | if let Some(iv_data) = iv { |
| 1916 | let iv_bytes = iv_data.borrow_buf(); |
| 1917 | // struct af_alg_iv { __u32 ivlen; __u8 iv[]; } |
| 1918 | let iv_struct_size = 4 + iv_bytes.len(); |
| 1919 | let space = unsafe { libc::CMSG_SPACE(iv_struct_size as u32) } as usize; |
| 1920 | let old_len = control_buf.len(); |
| 1921 | control_buf.resize(old_len + space, 0u8); |
| 1922 | |
| 1923 | let cmsg = control_buf[old_len..].as_mut_ptr() as *mut libc::cmsghdr; |
| 1924 | unsafe { |
| 1925 | (*cmsg).cmsg_len = libc::CMSG_LEN(iv_struct_size as u32) as _; |
| 1926 | (*cmsg).cmsg_level = libc::SOL_ALG; |
| 1927 | (*cmsg).cmsg_type = libc::ALG_SET_IV; |
| 1928 | let data = libc::CMSG_DATA(cmsg); |
| 1929 | // Write ivlen |
| 1930 | let ivlen = (iv_bytes.len() as u32).to_ne_bytes(); |
| 1931 | core::ptr::copy_nonoverlapping(ivlen.as_ptr(), data, 4); |
| 1932 | // Write iv |
| 1933 | core::ptr::copy_nonoverlapping(iv_bytes.as_ptr(), data.add(4), iv_bytes.len()); |
| 1934 | } |
| 1935 | } |