protected unsafe override void ReadProcessMemory( byte[] buffer, IntPtr processAddress, int length) { fixed(byte *bytePtr = buffer) { var ptr = (IntPtr)bytePtr; var localIo = new Iovec { IovBase = ptr.ToPointer(), IovLen = length, }; var remoteIo = new Iovec { IovBase = processAddress.ToPointer(), IovLen = length, }; var res = ProcessVmReadV(this.ProcessId, &localIo, 1, &remoteIo, 1, 0); if (res != -1) { // Array.Copy(*(byte[]*)ptr, 0, buffer, 0, length); Marshal.Copy(ptr, buffer, 0, length); } else { throw new Exception("Error while trying to read memory through from process_vm_readv. Check errno."); } } }
// Might return short reads unsafe int ReadShort(byte[] buffer, int offset, int length, UnixFDArray fdArray) { if (length < 0 || offset < 0 || length + offset < length || length + offset > buffer.Length) { throw new ArgumentException(); fixed(byte *ptr = buffer, cmsgPtr = cmsgBuffer) { var iovecs = new Iovec[] { new Iovec { iov_base = (IntPtr)(ptr + offset), iov_len = (ulong)length, }, }; var msghdr = new Msghdr { msg_iov = iovecs, msg_iovlen = 1, msg_control = cmsgBuffer, msg_controllen = cmsgBuffer.Length, }; long r; do { r = Syscall.recvmsg((int)SocketHandle, msghdr, 0); } while (UnixMarshal.ShouldRetrySyscall((int)r)); for (long cOffset = Syscall.CMSG_FIRSTHDR(msghdr); cOffset != -1; cOffset = Syscall.CMSG_NXTHDR(msghdr, cOffset)) { var recvHdr = Cmsghdr.ReadFromBuffer(msghdr, cOffset); if (recvHdr.cmsg_level != UnixSocketProtocol.SOL_SOCKET) { continue; } if (recvHdr.cmsg_type != UnixSocketControlMessage.SCM_RIGHTS) { continue; } var recvDataOffset = Syscall.CMSG_DATA(msghdr, cOffset); var bytes = recvHdr.cmsg_len - (recvDataOffset - cOffset); var fdCount = bytes / sizeof(int); for (int i = 0; i < fdCount; i++) { fdArray.FDs.Add(new UnixFD(((int *)(cmsgPtr + recvDataOffset))[i])); } } if ((msghdr.msg_flags & MessageFlags.MSG_CTRUNC) != 0) { throw new Exception("Control message truncated (probably file descriptors lost)"); } return((int)r); } }
public unsafe void WriteGather(long position, byte*[] pages) { var locs = new Iovec[pages.Length]; for (int i = 0; i < locs.Length; i++) { locs[i].iov_base = new IntPtr(pages[i]); locs[i].iov_len = AbstractPager.PageSize; } var result = Syscall.pwritev(_fd, locs, position); if(result == -1) PosixHelper.ThrowLastError(Marshal.GetLastWin32Error()); }
public unsafe void SendMsgRecvMsg() { WithSocketPair((so1, so2) => { long ret; var buffer1 = new byte[] { 42, 43, 44 }; fixed(byte *ptr_buffer1 = buffer1) { var iovecs1 = new Iovec[] { new Iovec { iov_base = (IntPtr)ptr_buffer1, iov_len = (ulong)buffer1.Length, }, }; var msghdr1 = new Msghdr { msg_iov = iovecs1, msg_iovlen = 1, }; ret = Syscall.sendmsg(so1, msghdr1, 0); } if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } var buffer2 = new byte[1024]; fixed(byte *ptr_buffer2 = buffer2) { var iovecs2 = new Iovec[] { new Iovec { iov_base = (IntPtr)ptr_buffer2, iov_len = (ulong)buffer2.Length, }, }; var msghdr2 = new Msghdr { msg_iov = iovecs2, msg_iovlen = 1, }; ret = Syscall.recvmsg(so2, msghdr2, 0); } if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } Assert.AreEqual(buffer1.Length, ret); for (int i = 0; i < buffer1.Length; i++) { Assert.AreEqual(buffer1[i], buffer2[i]); } }); }
public unsafe void ControlMsg (bool useMultipleControlMessages) { // Create two socket pairs and send inner_so1 and inner_so2 over the other socket pair using SCM_RIGHTS WithSocketPair ((inner_so1, inner_so2) => { WithSocketPair ((so1, so2) => { byte[] cmsg; Msghdr msghdr1; long offset; if (useMultipleControlMessages) { // Create two SCM_RIGHTS control messages cmsg = new byte[2 * Syscall.CMSG_SPACE (sizeof (int))]; var hdr = new Cmsghdr { cmsg_len = (long) Syscall.CMSG_LEN (sizeof (int)), cmsg_level = UnixSocketProtocol.SOL_SOCKET, cmsg_type = UnixSocketControlMessage.SCM_RIGHTS, }; msghdr1 = new Msghdr { msg_control = cmsg, msg_controllen = cmsg.Length, }; offset = 0; hdr.WriteToBuffer (msghdr1, offset); var dataOffset = Syscall.CMSG_DATA (msghdr1, offset); fixed (byte* ptr = msghdr1.msg_control) { ((int*) (ptr + dataOffset))[0] = inner_so1; } offset = (long) Syscall.CMSG_SPACE (sizeof (int)); hdr.WriteToBuffer (msghdr1, offset); dataOffset = Syscall.CMSG_DATA (msghdr1, offset); fixed (byte* ptr = msghdr1.msg_control) { ((int*) (ptr + dataOffset))[0] = inner_so2; } } else { // Create one SCM_RIGHTS control message cmsg = new byte[Syscall.CMSG_SPACE (2 * sizeof (int))]; var hdr = new Cmsghdr { cmsg_len = (long) Syscall.CMSG_LEN (2 * sizeof (int)), cmsg_level = UnixSocketProtocol.SOL_SOCKET, cmsg_type = UnixSocketControlMessage.SCM_RIGHTS, }; msghdr1 = new Msghdr { msg_control = cmsg, msg_controllen = cmsg.Length, }; offset = 0; hdr.WriteToBuffer (msghdr1, offset); var dataOffset = Syscall.CMSG_DATA (msghdr1, offset); fixed (byte* ptr = msghdr1.msg_control) { ((int*) (ptr + dataOffset))[0] = inner_so1; ((int*) (ptr + dataOffset))[1] = inner_so2; } } long ret; var buffer1 = new byte[] { 42, 43, 44 }; fixed (byte* ptr_buffer1 = buffer1) { var iovecs1 = new Iovec[] { new Iovec { iov_base = (IntPtr) ptr_buffer1, iov_len = (ulong) buffer1.Length, }, }; msghdr1.msg_iov = iovecs1; msghdr1.msg_iovlen = 1; // Send message twice ret = Syscall.sendmsg (so1, msghdr1, 0); if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); ret = Syscall.sendmsg (so1, msghdr1, 0); if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); } // Receive without control message buffer var buffer2 = new byte[1024]; var msghdr2 = new Msghdr { }; fixed (byte* ptr_buffer2 = buffer2) { var iovecs2 = new Iovec[] { new Iovec { iov_base = (IntPtr) ptr_buffer2, iov_len = (ulong) buffer2.Length, }, }; msghdr2.msg_iov = iovecs2; msghdr2.msg_iovlen = 1; ret = Syscall.recvmsg (so2, msghdr2, 0); } if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); if (useMultipleControlMessages) // This assertion fails on OSX for some reason Assert.IsTrue ((msghdr2.msg_flags & MessageFlags.MSG_CTRUNC) != 0); // Control message has been truncated Assert.AreEqual (buffer1.Length, ret); for (int i = 0; i < buffer1.Length; i++) Assert.AreEqual (buffer1[i], buffer2[i]); // Receive with control message buffer buffer2 = new byte[1024]; var cmsg2 = new byte[1024]; msghdr2 = new Msghdr { msg_control = cmsg2, msg_controllen = cmsg2.Length, }; fixed (byte* ptr_buffer2 = buffer2) { var iovecs2 = new Iovec[] { new Iovec { iov_base = (IntPtr) ptr_buffer2, iov_len = (ulong) buffer2.Length, }, }; msghdr2.msg_iov = iovecs2; msghdr2.msg_iovlen = 1; ret = Syscall.recvmsg (so2, msghdr2, 0); } if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); var fds = new global::System.Collections.Generic.List<int> (); for (offset = Syscall.CMSG_FIRSTHDR (msghdr2); offset != -1; offset = Syscall.CMSG_NXTHDR (msghdr2, offset)) { var recvHdr = Cmsghdr.ReadFromBuffer (msghdr2, offset); var recvDataOffset = Syscall.CMSG_DATA (msghdr2, offset); var bytes = recvHdr.cmsg_len - (recvDataOffset - offset); Assert.AreEqual (bytes % sizeof (int), 0); var fdCount = bytes / sizeof (int); fixed (byte* ptr = msghdr2.msg_control) for (int i = 0; i < fdCount; i++) fds.Add (((int*) (ptr + recvDataOffset))[i]); } try { Assert.IsTrue ((msghdr2.msg_flags & MessageFlags.MSG_CTRUNC) == 0); // Control message has not been truncated Assert.AreEqual (buffer1.Length, ret); for (int i = 0; i < buffer1.Length; i++) Assert.AreEqual (buffer1[i], buffer2[i]); Assert.AreEqual (fds.Count, 2); // Send message over the first received fd and receive it over inner_so2 var buffer3 = new byte[] { 16, 17 }; ret = Syscall.send (fds[0], buffer3, (ulong) buffer3.Length, 0); if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); var buffer4 = new byte[1024]; ret = Syscall.recv (inner_so2, buffer4, (ulong) buffer4.Length, 0); if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); Assert.AreEqual (buffer3.Length, ret); for (int i = 0; i < buffer3.Length; i++) Assert.AreEqual (buffer3[i], buffer4[i]); // Send message over inner_so1 and receive it second received fd var buffer5 = new byte[] { 10, 40, 0, 1 }; ret = Syscall.send (inner_so1, buffer5, (ulong) buffer5.Length, 0); if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); var buffer6 = new byte[1024]; ret = Syscall.recv (fds[1], buffer6, (ulong) buffer6.Length, 0); if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); Assert.AreEqual (buffer5.Length, ret); for (int i = 0; i < buffer5.Length; i++) Assert.AreEqual (buffer5[i], buffer6[i]); } finally { foreach (var fd in fds) if (Syscall.close (fd) < 0) UnixMarshal.ThrowExceptionForLastError (); } }); }); }
public unsafe void SendMsgRecvMsgAddress () { WithSockets (UnixAddressFamily.AF_INET, UnixSocketType.SOCK_DGRAM, UnixSocketProtocol.IPPROTO_UDP, (so1, so2) => { // Bind UDP socket so1 to 127.0.0.1 with dynamic port var address = new SockaddrIn { sin_family = UnixAddressFamily.AF_INET, sin_port = Syscall.htons (0), sin_addr = new InAddr (127, 0, 0, 1), }; if (Syscall.bind (so1, address) < 0) UnixMarshal.ThrowExceptionForLastError (); // Get actual port number using getsockname() var actualAddress = new SockaddrIn (); if (Syscall.getsockname (so1, actualAddress) < 0) UnixMarshal.ThrowExceptionForLastError (); Assert.AreEqual (actualAddress.sa_family, UnixAddressFamily.AF_INET); var port = Syscall.ntohs (actualAddress.sin_port); Assert.IsTrue (port != 0); var remoteAddress = new SockaddrIn { sin_family = UnixAddressFamily.AF_INET, sin_port = Syscall.htons (port), sin_addr = new InAddr (127, 0, 0, 1), }; // Send and receive a few bytes long ret; var buffer1 = new byte[] { 42, 43, 44 }; fixed (byte* ptr_buffer1 = buffer1) { var iovecs1 = new Iovec[] { new Iovec { iov_base = (IntPtr) ptr_buffer1, iov_len = (ulong) buffer1.Length, }, }; var msghdr1 = new Msghdr { msg_name = remoteAddress, msg_iov = iovecs1, msg_iovlen = 1, }; ret = Syscall.sendmsg (so2, msghdr1, 0); msghdr1.msg_name = remoteAddress.ToSockaddrStorage (); if (ret >= 0) ret = Syscall.sendmsg (so2, msghdr1, 0); } if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); var senderAddress = new SockaddrIn (); var senderAddressStorage = new SockaddrStorage (); var buffer2 = new byte[1024]; var buffer3 = new byte[1024]; fixed (byte* ptr_buffer2 = buffer2, ptr_buffer3 = buffer3) { var iovecs2 = new Iovec[] { new Iovec { iov_base = (IntPtr) ptr_buffer2, iov_len = (ulong) buffer2.Length, }, }; var msghdr2 = new Msghdr { msg_name = senderAddress, msg_iov = iovecs2, msg_iovlen = 1, }; ret = Syscall.recvmsg (so1, msghdr2, 0); msghdr2.msg_name = senderAddressStorage; iovecs2[0].iov_base = (IntPtr) ptr_buffer3; if (ret >= 0) ret = Syscall.recvmsg (so1, msghdr2, 0); } if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); Assert.AreEqual (senderAddress.sa_family, UnixAddressFamily.AF_INET); Assert.AreEqual (senderAddress.sin_addr, new InAddr (127, 0, 0, 1)); var senderAddress2 = SockaddrIn.FromSockaddrStorage (senderAddressStorage); Assert.AreEqual (senderAddress2.sa_family, UnixAddressFamily.AF_INET); Assert.AreEqual (senderAddress2.sin_addr, new InAddr (127, 0, 0, 1)); Assert.AreEqual (buffer1.Length, ret); for (int i = 0; i < buffer1.Length; i++) Assert.AreEqual (buffer1[i], buffer2[i]); for (int i = 0; i < buffer1.Length; i++) Assert.AreEqual (buffer1[i], buffer3[i]); }); }
public unsafe void SendMsgRecvMsg () { WithSocketPair ((so1, so2) => { long ret; var buffer1 = new byte[] { 42, 43, 44 }; fixed (byte* ptr_buffer1 = buffer1) { var iovecs1 = new Iovec[] { new Iovec { iov_base = (IntPtr) ptr_buffer1, iov_len = (ulong) buffer1.Length, }, }; var msghdr1 = new Msghdr { msg_iov = iovecs1, msg_iovlen = 1, }; ret = Syscall.sendmsg (so1, msghdr1, 0); } if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); var buffer2 = new byte[1024]; fixed (byte* ptr_buffer2 = buffer2) { var iovecs2 = new Iovec[] { new Iovec { iov_base = (IntPtr) ptr_buffer2, iov_len = (ulong) buffer2.Length, }, }; var msghdr2 = new Msghdr { msg_iov = iovecs2, msg_iovlen = 1, }; ret = Syscall.recvmsg (so2, msghdr2, 0); } if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); Assert.AreEqual (buffer1.Length, ret); for (int i = 0; i < buffer1.Length; i++) Assert.AreEqual (buffer1[i], buffer2[i]); }); }
public static bool TryCopy (IntPtr source, out Iovec destination) { return ToIovec (source, out destination) == 0; }
private static extern int ToIovec (IntPtr source, out Iovec destination);
public static bool TryCopy (ref Iovec source, IntPtr destination) { return FromIovec (ref source, destination) == 0; }
private static extern int FromIovec (ref Iovec source, IntPtr destination);
public unsafe void ControlMsg(bool useMultipleControlMessages) { // Create two socket pairs and send inner_so1 and inner_so2 over the other socket pair using SCM_RIGHTS WithSocketPair((inner_so1, inner_so2) => { WithSocketPair((so1, so2) => { byte[] cmsg; Msghdr msghdr1; long offset; if (useMultipleControlMessages) { // Create two SCM_RIGHTS control messages cmsg = new byte[2 * Syscall.CMSG_SPACE(sizeof(int))]; var hdr = new Cmsghdr { cmsg_len = (long)Syscall.CMSG_LEN(sizeof(int)), cmsg_level = UnixSocketProtocol.SOL_SOCKET, cmsg_type = UnixSocketControlMessage.SCM_RIGHTS, }; msghdr1 = new Msghdr { msg_control = cmsg, msg_controllen = cmsg.Length, }; offset = 0; hdr.WriteToBuffer(msghdr1, offset); var dataOffset = Syscall.CMSG_DATA(msghdr1, offset); fixed(byte *ptr = msghdr1.msg_control) { ((int *)(ptr + dataOffset))[0] = inner_so1; } offset = (long)Syscall.CMSG_SPACE(sizeof(int)); hdr.WriteToBuffer(msghdr1, offset); dataOffset = Syscall.CMSG_DATA(msghdr1, offset); fixed(byte *ptr = msghdr1.msg_control) { ((int *)(ptr + dataOffset))[0] = inner_so2; } } else { // Create one SCM_RIGHTS control message cmsg = new byte[Syscall.CMSG_SPACE(2 * sizeof(int))]; var hdr = new Cmsghdr { cmsg_len = (long)Syscall.CMSG_LEN(2 * sizeof(int)), cmsg_level = UnixSocketProtocol.SOL_SOCKET, cmsg_type = UnixSocketControlMessage.SCM_RIGHTS, }; msghdr1 = new Msghdr { msg_control = cmsg, msg_controllen = cmsg.Length, }; offset = 0; hdr.WriteToBuffer(msghdr1, offset); var dataOffset = Syscall.CMSG_DATA(msghdr1, offset); fixed(byte *ptr = msghdr1.msg_control) { ((int *)(ptr + dataOffset))[0] = inner_so1; ((int *)(ptr + dataOffset))[1] = inner_so2; } } long ret; var buffer1 = new byte[] { 42, 43, 44 }; fixed(byte *ptr_buffer1 = buffer1) { var iovecs1 = new Iovec[] { new Iovec { iov_base = (IntPtr)ptr_buffer1, iov_len = (ulong)buffer1.Length, }, }; msghdr1.msg_iov = iovecs1; msghdr1.msg_iovlen = 1; // Send message twice ret = Syscall.sendmsg(so1, msghdr1, 0); if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } ret = Syscall.sendmsg(so1, msghdr1, 0); if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } } // Receive without control message buffer var buffer2 = new byte[1024]; var msghdr2 = new Msghdr { }; fixed(byte *ptr_buffer2 = buffer2) { var iovecs2 = new Iovec[] { new Iovec { iov_base = (IntPtr)ptr_buffer2, iov_len = (ulong)buffer2.Length, }, }; msghdr2.msg_iov = iovecs2; msghdr2.msg_iovlen = 1; ret = Syscall.recvmsg(so2, msghdr2, 0); } if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } if (useMultipleControlMessages) // This assertion fails on OSX for some reason { Assert.IsTrue((msghdr2.msg_flags & MessageFlags.MSG_CTRUNC) != 0); // Control message has been truncated } Assert.AreEqual(buffer1.Length, ret); for (int i = 0; i < buffer1.Length; i++) { Assert.AreEqual(buffer1[i], buffer2[i]); } // Receive with control message buffer buffer2 = new byte[1024]; var cmsg2 = new byte[1024]; msghdr2 = new Msghdr { msg_control = cmsg2, msg_controllen = cmsg2.Length, }; fixed(byte *ptr_buffer2 = buffer2) { var iovecs2 = new Iovec[] { new Iovec { iov_base = (IntPtr)ptr_buffer2, iov_len = (ulong)buffer2.Length, }, }; msghdr2.msg_iov = iovecs2; msghdr2.msg_iovlen = 1; ret = Syscall.recvmsg(so2, msghdr2, 0); } if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } var fds = new global::System.Collections.Generic.List <int> (); for (offset = Syscall.CMSG_FIRSTHDR(msghdr2); offset != -1; offset = Syscall.CMSG_NXTHDR(msghdr2, offset)) { var recvHdr = Cmsghdr.ReadFromBuffer(msghdr2, offset); var recvDataOffset = Syscall.CMSG_DATA(msghdr2, offset); var bytes = recvHdr.cmsg_len - (recvDataOffset - offset); Assert.AreEqual(bytes % sizeof(int), 0); var fdCount = bytes / sizeof(int); fixed(byte *ptr = msghdr2.msg_control) for (int i = 0; i < fdCount; i++) { fds.Add(((int *)(ptr + recvDataOffset))[i]); } } try { Assert.IsTrue((msghdr2.msg_flags & MessageFlags.MSG_CTRUNC) == 0); // Control message has not been truncated Assert.AreEqual(buffer1.Length, ret); for (int i = 0; i < buffer1.Length; i++) { Assert.AreEqual(buffer1[i], buffer2[i]); } Assert.AreEqual(fds.Count, 2); // Send message over the first received fd and receive it over inner_so2 var buffer3 = new byte[] { 16, 17 }; ret = Syscall.send(fds[0], buffer3, (ulong)buffer3.Length, 0); if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } var buffer4 = new byte[1024]; ret = Syscall.recv(inner_so2, buffer4, (ulong)buffer4.Length, 0); if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } Assert.AreEqual(buffer3.Length, ret); for (int i = 0; i < buffer3.Length; i++) { Assert.AreEqual(buffer3[i], buffer4[i]); } // Send message over inner_so1 and receive it second received fd var buffer5 = new byte[] { 10, 40, 0, 1 }; ret = Syscall.send(inner_so1, buffer5, (ulong)buffer5.Length, 0); if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } var buffer6 = new byte[1024]; ret = Syscall.recv(fds[1], buffer6, (ulong)buffer6.Length, 0); if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } Assert.AreEqual(buffer5.Length, ret); for (int i = 0; i < buffer5.Length; i++) { Assert.AreEqual(buffer5[i], buffer6[i]); } } finally { foreach (var fd in fds) { if (Syscall.close(fd) < 0) { UnixMarshal.ThrowExceptionForLastError(); } } } }); }); }
[ExpectedException(typeof(ArgumentOutOfRangeException))] // IPPROTO_UDP not supported #endif public unsafe void SendMsgRecvMsgAddress() { WithSockets(UnixAddressFamily.AF_INET, UnixSocketType.SOCK_DGRAM, UnixSocketProtocol.IPPROTO_UDP, (so1, so2) => { // Bind UDP socket so1 to 127.0.0.1 with dynamic port var address = new SockaddrIn { sin_family = UnixAddressFamily.AF_INET, sin_port = Syscall.htons(0), sin_addr = new InAddr(127, 0, 0, 1), }; if (Syscall.bind(so1, address) < 0) { UnixMarshal.ThrowExceptionForLastError(); } // Get actual port number using getsockname() var actualAddress = new SockaddrIn(); if (Syscall.getsockname(so1, actualAddress) < 0) { UnixMarshal.ThrowExceptionForLastError(); } Assert.AreEqual(actualAddress.sa_family, UnixAddressFamily.AF_INET); var port = Syscall.ntohs(actualAddress.sin_port); Assert.IsTrue(port != 0); var remoteAddress = new SockaddrIn { sin_family = UnixAddressFamily.AF_INET, sin_port = Syscall.htons(port), sin_addr = new InAddr(127, 0, 0, 1), }; // Send and receive a few bytes long ret; var buffer1 = new byte[] { 42, 43, 44 }; fixed(byte *ptr_buffer1 = buffer1) { var iovecs1 = new Iovec[] { new Iovec { iov_base = (IntPtr)ptr_buffer1, iov_len = (ulong)buffer1.Length, }, }; var msghdr1 = new Msghdr { msg_name = remoteAddress, msg_iov = iovecs1, msg_iovlen = 1, }; ret = Syscall.sendmsg(so2, msghdr1, 0); msghdr1.msg_name = remoteAddress.ToSockaddrStorage(); if (ret >= 0) { ret = Syscall.sendmsg(so2, msghdr1, 0); } } if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } var senderAddress = new SockaddrIn(); var senderAddressStorage = new SockaddrStorage(); var buffer2 = new byte[1024]; var buffer3 = new byte[1024]; fixed(byte *ptr_buffer2 = buffer2, ptr_buffer3 = buffer3) { var iovecs2 = new Iovec[] { new Iovec { iov_base = (IntPtr)ptr_buffer2, iov_len = (ulong)buffer2.Length, }, }; var msghdr2 = new Msghdr { msg_name = senderAddress, msg_iov = iovecs2, msg_iovlen = 1, }; ret = Syscall.recvmsg(so1, msghdr2, 0); msghdr2.msg_name = senderAddressStorage; iovecs2[0].iov_base = (IntPtr)ptr_buffer3; if (ret >= 0) { ret = Syscall.recvmsg(so1, msghdr2, 0); } } if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } Assert.AreEqual(senderAddress.sa_family, UnixAddressFamily.AF_INET); Assert.AreEqual(senderAddress.sin_addr, new InAddr(127, 0, 0, 1)); var senderAddress2 = SockaddrIn.FromSockaddrStorage(senderAddressStorage); Assert.AreEqual(senderAddress2.sa_family, UnixAddressFamily.AF_INET); Assert.AreEqual(senderAddress2.sin_addr, new InAddr(127, 0, 0, 1)); Assert.AreEqual(buffer1.Length, ret); for (int i = 0; i < buffer1.Length; i++) { Assert.AreEqual(buffer1[i], buffer2[i]); } for (int i = 0; i < buffer1.Length; i++) { Assert.AreEqual(buffer1[i], buffer3[i]); } }); }
// Send the two buffers and the FDs using sendmsg(), don't handle short writes // length1 + length2 must not be 0 public unsafe long SendmsgShort(byte[] buffer1, long offset1, long length1, byte[] buffer2, long offset2, long length2, DBus.Protocol.UnixFDArray fds) { //Console.WriteLine ("SendmsgShort (X, {0}, {1}, {2}, {3}, {4}, {5})", offset1, length1, buffer2 == null ? "-" : "Y", offset2, length2, fds == null ? "-" : "" + fds.FDs.Count); AssertValidBuffer(buffer1, offset1, length1); if (buffer2 == null) { if (length2 != 0) { throw new ArgumentOutOfRangeException("length2", "!= 0 while buffer2 == null"); } offset2 = 0; } else { AssertValidBuffer(buffer2, offset2, length2); } fixed(byte *ptr1 = buffer1, ptr2 = buffer2) { var iovecs = new Iovec[] { new Iovec { iov_base = (IntPtr)(ptr1 + offset1), iov_len = (ulong)length1, }, new Iovec { iov_base = (IntPtr)(ptr2 + offset2), iov_len = (ulong)length2, }, }; /* Simulate short writes * if (iovecs[0].iov_len == 0) { * iovecs[1].iov_len = Math.Min (iovecs[1].iov_len, 5); * } else { * iovecs[0].iov_len = Math.Min (iovecs[0].iov_len, 5); * iovecs[1].iov_len = 0; * } */ byte[] cmsg = null; // Create copy of FDs to prevent the user from Dispose()ing the // FDs in another thread between writing the FDs into the cmsg // buffer and calling sendmsg() using (var fds2 = fds == null ? null : fds.Clone()) { int fdCount = fds2 == null ? 0 : fds2.FDs.Count; if (fdCount != 0) { // Create one SCM_RIGHTS control message cmsg = new byte[Syscall.CMSG_SPACE((uint)fdCount * sizeof(int))]; } var msghdr = new Msghdr { msg_iov = iovecs, msg_iovlen = length2 == 0 ? 1 : 2, msg_control = cmsg, msg_controllen = cmsg == null ? 0 : cmsg.Length, }; if (fdCount != 0) { var hdr = new Cmsghdr { cmsg_len = (long)Syscall.CMSG_LEN((uint)fdCount * sizeof(int)), cmsg_level = UnixSocketProtocol.SOL_SOCKET, cmsg_type = UnixSocketControlMessage.SCM_RIGHTS, }; hdr.WriteToBuffer(msghdr, 0); var dataOffset = Syscall.CMSG_DATA(msghdr, 0); fixed(byte *ptr = cmsg) { for (int i = 0; i < fdCount; i++) { ((int *)(ptr + dataOffset))[i] = fds2.FDs[i].Handle; } } } long r; do { r = Syscall.sendmsg(fd, msghdr, MessageFlags.MSG_NOSIGNAL); } while (UnixMarshal.ShouldRetrySyscall((int)r)); if (r < 0) { UnixMarshal.ThrowExceptionForLastError(); } if (r == 0) { throw new Exception("sendmsg() returned 0"); } return(r); } } }