예제 #1
0
        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.");
                }
            }
        }
예제 #2
0
        // 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);
                }
        }
예제 #3
0
		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());
		}
예제 #4
0
        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]);
                }
            });
        }
예제 #5
0
파일: SocketTest.cs 프로젝트: ZZHGit/mono
		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 ();
					}
				});
			});
		}
예제 #6
0
파일: SocketTest.cs 프로젝트: ZZHGit/mono
		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]);
			});
		}
예제 #7
0
파일: SocketTest.cs 프로젝트: ZZHGit/mono
		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]);
			});
		}
예제 #8
0
		public static bool TryCopy (IntPtr source, out Iovec destination)
		{
			return ToIovec (source, out destination) == 0;
		}
예제 #9
0
		private static extern int ToIovec (IntPtr source, out Iovec destination);
예제 #10
0
		public static bool TryCopy (ref Iovec source, IntPtr destination)
		{
			return FromIovec (ref source, destination) == 0;
		}
예제 #11
0
		private static extern int FromIovec (ref Iovec source, IntPtr destination);
예제 #12
0
        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();
                            }
                        }
                    }
                });
            });
        }
예제 #13
0
        [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]);
                }
            });
        }
예제 #14
0
        // 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);
                }
            }
        }