Ejemplo n.º 1
0
        public override unsafe int Read(byte[] buffer, int offset, int length)
        {
            AssertValidBuffer(buffer, offset, length);

            long r = 0;

            fixed(byte *buf = buffer)
            {
                do
                {
                    r = Syscall.read(fd, buf + offset, (ulong)length);
                } while (UnixMarshal.ShouldRetrySyscall((int)r));
                if (r < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }
                return((int)r);
            }
        }
Ejemplo n.º 2
0
        public void SockOpt()
        {
            WithSockets(UnixAddressFamily.AF_UNIX, UnixSocketType.SOCK_STREAM, 0, (so1, so2) => {
                int value;
                if (Syscall.getsockopt(so1, UnixSocketProtocol.SOL_SOCKET, UnixSocketOptionName.SO_REUSEADDR, out value) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }
                Assert.AreEqual(0, value);

                // Set SO_REUSEADDR to 1
                if (Syscall.setsockopt(so1, UnixSocketProtocol.SOL_SOCKET, UnixSocketOptionName.SO_REUSEADDR, 1) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }

                // Get and check SO_REUSEADDR
                if (Syscall.getsockopt(so1, UnixSocketProtocol.SOL_SOCKET, UnixSocketOptionName.SO_REUSEADDR, out value) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }
                Assert.AreNotEqual(0, value);

                // Set SO_REUSEADDR to 0
                if (Syscall.setsockopt(so1, UnixSocketProtocol.SOL_SOCKET, UnixSocketOptionName.SO_REUSEADDR, new byte[10], 4) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }

                // Get and check SO_REUSEADDR
                var buffer = new byte[15];
                long size  = 12;
                if (Syscall.getsockopt(so1, UnixSocketProtocol.SOL_SOCKET, UnixSocketOptionName.SO_REUSEADDR, buffer, ref size) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }
                Assert.AreEqual(size, 4);
                for (int i = 0; i < size; i++)
                {
                    Assert.AreEqual(buffer[i], 0);
                }
            });
        }
Ejemplo n.º 3
0
        public static void Disable(SafeFileHandle handle)
        {
            if (!Runtime.IsMacOS)
            {
                return;
            }

            long r;

            do
            {
                r = fcntl(handle.DangerousGetHandle().ToInt32(), MAC_F_NOCACHE, 1);
            } while (UnixMarshal.ShouldRetrySyscall((int)r));

            if (r == -1)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }
        }
Ejemplo n.º 4
0
        void WithSocketPair(Action <int, int> f)
        {
            int socket1, socket2;

            if (Syscall.socketpair(UnixAddressFamily.AF_UNIX, UnixSocketType.SOCK_STREAM, 0, out socket1, out socket2) < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }
            try {
                SetTimeout(socket1);
                SetTimeout(socket2);

                f(socket1, socket2);
            } finally {
                int r0 = Syscall.close(socket1);
                int r1 = Syscall.close(socket2);
                if (r0 < 0 || r1 < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }
            }
        }
Ejemplo n.º 5
0
        public void SockOptLinger()
        {
            WithSockets(UnixAddressFamily.AF_INET, UnixSocketType.SOCK_STREAM, UnixSocketProtocol.IPPROTO_TCP, (so1, so2) => {
                Linger linger = new Linger {
                    l_onoff  = 1,
                    l_linger = 42,
                };
                // Set SO_LINGER
                if (Syscall.setsockopt(so1, UnixSocketProtocol.SOL_SOCKET, UnixSocketOptionName.SO_LINGER, linger) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }

                // Get and check SO_LINGER
                Linger value;
                if (Syscall.getsockopt(so1, UnixSocketProtocol.SOL_SOCKET, UnixSocketOptionName.SO_LINGER, out value) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }
                Assert.AreEqual(linger, value);
            });
        }
Ejemplo n.º 6
0
        public unsafe void PWrite(SafeFileHandle handle, ReadOnlySpan <byte> data, ulong position)
        {
            fixed(void *dataptr = data)
            {
                long result;

                do
                {
                    result = Mono.Unix.Native.Syscall.pwrite((int)handle.DangerousGetHandle(), dataptr,
                                                             (ulong)data.Length, (long)position);
                } while (UnixMarshal.ShouldRetrySyscall((int)result));

                if (result == -1)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }
                if (result != data.Length)
                {
                    throw new BTDBException($"Out of disk space written {result} out of {data.Length} at {position}");
                }
            }
        }
Ejemplo n.º 7
0
        public static int Read(SafeFileHandle handle, byte *buffer, int offset, int count)
        {
#if !__MonoCS__ && !USE_UNIX_IO
            var read = 0;

            if (!WinNative.ReadFile(handle, buffer, count, ref read, 0))
            {
                throw new Win32Exception();
            }
            return(read);
#else
            int r;
            do
            {
                r = (int)Syscall.read(handle.DangerousGetHandle().ToInt32(), buffer, (ulong)count);
            } while (UnixMarshal.ShouldRetrySyscall((int)r));
            if (r == -1)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }
            return(count);
#endif
        }
Ejemplo n.º 8
0
        public override unsafe void Write(byte[] buffer, int offset, int length)
        {
            AssertValidBuffer(buffer, offset, length);

            int  pos = 0;
            long r   = 0;

            fixed(byte *buf = buffer)
            {
                while (pos < length)
                {
                    do
                    {
                        r = Syscall.write(fd, buf + offset + pos, (ulong)length);
                    } while (UnixMarshal.ShouldRetrySyscall((int)r));
                    if (r < 0)
                    {
                        UnixMarshal.ThrowExceptionForLastError();
                    }
                    pos += (int)r;
                }
            }
        }
Ejemplo n.º 9
0
        public void readlinkat_char()
        {
            if (!HaveReadlinkAt)
            {
                return;
            }

            foreach (string s in Targets)
            {
                CreateLink(s);

                var sb = new StringBuilder(256);
                do
                {
                    int oldCapacity = sb.Capacity;
                    int r           = Syscall.readlinkat(TempFD, "link", sb);
                    Assert.AreEqual(oldCapacity, sb.Capacity);
                    if (r < 0)
                    {
                        UnixMarshal.ThrowExceptionForLastError();
                    }
                    Assert.AreEqual(r, sb.Length);
                    Assert.GreaterOrEqual(sb.Capacity, r);
                    if (r == sb.Capacity)
                    {
                        checked { sb.Capacity *= 2; }
                    }
                    else
                    {
                        break;
                    }
                } while (true);
                var target = sb.ToString();

                Assert.AreEqual(s, target);
            }
        }
Ejemplo n.º 10
0
        public void IPv6()
        {
            if (!Socket.OSSupportsIPv6)
            {
                Assert.Ignore("OS does not support IPv6.");
            }

            var address = new SockaddrIn6 {
                sin6_family = UnixAddressFamily.AF_INET6,
                sin6_port   = Syscall.htons(0),
                sin6_addr   = NativeConvert.ToIn6Addr(IPAddress.IPv6Loopback),
            };

            WithSockets(UnixAddressFamily.AF_INET6, UnixSocketType.SOCK_STREAM, 0, (so1, so2) => {
                if (Syscall.bind(so1, address) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }

                var address1Stor = new SockaddrStorage();
                if (Syscall.getsockname(so1, address1Stor) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }

                var address1 = new SockaddrIn6();
                address1Stor.CopyTo(address1);

                // Check getsockname(socket, null)
                if (Syscall.getsockname(so1, null) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }

                var address2 = new SockaddrIn6();
                if (Syscall.getsockname(so1, address2) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }

                Assert.AreEqual(address1, address2);
                Assert.IsTrue(Syscall.ntohs(address1.sin6_port) != 0);
                address1.sin6_port = 0;
                Assert.AreEqual(address, address1);

                var address3 = new Sockaddr();
                if (Syscall.getsockname(so1, address3) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }
                Assert.AreEqual(address.sa_family, address3.sa_family);

                // Try to store a sockaddr_in6 into a Sockaddr. Should fail because sockaddr_in6 should be larger than sockaddr_in
                var address4 = new SockaddrIn();
                if (Syscall.getsockname(so1, address4) == 0)
                {
                    Assert.Fail("getsockname() should have failed");
                }
                Assert.AreEqual(Errno.ENOBUFS, Stdlib.GetLastError());
            });
        }
Ejemplo n.º 11
0
        public UnixMultiProcessFileAppender(string fileName, ICreateFileParameters parameters) : base(fileName, parameters)
        {
            UnixFileInfo fileInfo   = null;
            bool         fileExists = false;

            try
            {
                fileInfo   = new UnixFileInfo(fileName);
                fileExists = fileInfo.Exists;
            }
            catch
            {
            }

            int fd = Syscall.open(fileName, OpenFlags.O_CREAT | OpenFlags.O_WRONLY | OpenFlags.O_APPEND, (FilePermissions)(6 | (6 << 3) | (6 << 6)));

            if (fd == -1)
            {
                if (Stdlib.GetLastError() == Errno.ENOENT && parameters.CreateDirs)
                {
                    string dirName = Path.GetDirectoryName(fileName);
                    if (!Directory.Exists(dirName) && parameters.CreateDirs)
                    {
                        Directory.CreateDirectory(dirName);
                    }

                    fd = Syscall.open(fileName, OpenFlags.O_CREAT | OpenFlags.O_WRONLY | OpenFlags.O_APPEND, (FilePermissions)(6 | (6 << 3) | (6 << 6)));
                }
            }
            if (fd == -1)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }

            try
            {
                _file = new UnixStream(fd, true);

                long filePosition = _file.Position;
                if (fileExists || filePosition > 0)
                {
                    if (fileInfo != null)
                    {
                        CreationTimeUtc = FileInfoHelper.LookupValidFileCreationTimeUtc(fileInfo, (f) => File.GetCreationTimeUtc(f.FullName), (f) => { f.Refresh(); return(f.LastStatusChangeTimeUtc); }, (f) => DateTime.UtcNow).Value;
                    }
                    else
                    {
                        CreationTimeUtc = FileInfoHelper.LookupValidFileCreationTimeUtc(fileName, (f) => File.GetCreationTimeUtc(f), (f) => DateTime.UtcNow).Value;
                    }
                }
                else
                {
                    // We actually created the file and eventually concurrent processes
                    CreationTimeUtc = DateTime.UtcNow;
                    File.SetCreationTimeUtc(FileName, CreationTimeUtc);
                }
            }
            catch
            {
                Syscall.close(fd);
                throw;
            }
        }
Ejemplo n.º 12
0
        public unsafe void TestMemfd()
        {
            int fd;

            try {
                fd = Syscall.memfd_create("mono-test", 0);
            } catch (EntryPointNotFoundException) {
                Assert.Ignore("memfd_create() not available");
                return;
            }
            if (fd < 0 && Stdlib.GetLastError() == Errno.ENOSYS)
            {
                // Might happen on a new libc + old kernel
                Assert.Ignore("memfd_create() returns ENOSYS");
            }
            if (fd < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }

            byte b = 42;

            if (Syscall.write(fd, &b, 1) < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }

            // Should fail with EPERM because MFD_ALLOW_SEALING was not used
            var res = Syscall.fcntl(fd, FcntlCommand.F_ADD_SEALS, SealType.F_SEAL_WRITE);

            Assert.AreEqual(-1, res);
            Assert.AreEqual(Errno.EPERM, Stdlib.GetLastError());

            //Stdlib.system ("ls -l /proc/$PPID/fd/");

            if (Syscall.close(fd) < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }

            // Call memfd_create with MFD_ALLOW_SEALING
            fd = Syscall.memfd_create("mono-test", MemfdFlags.MFD_CLOEXEC | MemfdFlags.MFD_ALLOW_SEALING);
            if (fd < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }

            if (Syscall.write(fd, &b, 1) < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }

            res = Syscall.fcntl(fd, FcntlCommand.F_GET_SEALS);
            if (res < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }
            // Need to convert the result to SealType
            SealType sealType = NativeConvert.ToSealType(res);

            Assert.AreEqual((SealType)0, sealType);

            if (Syscall.fcntl(fd, FcntlCommand.F_ADD_SEALS, SealType.F_SEAL_WRITE) < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }

            // Should fail with EPERM because the file was sealed for writing
            var lres = Syscall.write(fd, &b, 1);

            Assert.AreEqual(-1, lres);
            Assert.AreEqual(Errno.EPERM, Stdlib.GetLastError());

            res = Syscall.fcntl(fd, FcntlCommand.F_GET_SEALS);
            if (res < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }
            // Need to convert the result to SealType
            sealType = NativeConvert.ToSealType(res);
            Assert.AreEqual(SealType.F_SEAL_WRITE, sealType);

            //Stdlib.system ("ls -l /proc/$PPID/fd/");

            if (Syscall.close(fd) < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }
        }
Ejemplo n.º 13
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();
                            }
                        }
                    }
                });
            });
        }
Ejemplo n.º 14
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]);
                }
            });
        }
Ejemplo n.º 15
0
        public void UnixAccept()
        {
            var address  = new SockaddrUn(TempFolder + "/socket1");
            var address2 = SockaddrUn.FromSockaddrStorage(address.ToSockaddrStorage());

            Assert.AreEqual(address, address2);

            WithSockets(UnixAddressFamily.AF_UNIX, UnixSocketType.SOCK_STREAM, 0, (so1, so2) => {
                if (Syscall.bind(so1, address) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }

                if (Syscall.listen(so1, 5) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }

                if (Syscall.connect(so2, address) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }

                var address3 = new SockaddrUn();
                if (Syscall.getsockname(so1, address3) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }
                Assert.AreEqual(address, address3);

                var address4 = new SockaddrStorage();
                if (Syscall.getsockname(so1, address4) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }
                Assert.AreEqual(UnixAddressFamily.AF_UNIX, address4.sa_family);
                Assert.AreEqual(address3, SockaddrUn.FromSockaddrStorage(address4));

                var address5 = new SockaddrUn();
                if (Syscall.getsockname(so1, address5) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }
                Assert.AreEqual(UnixAddressFamily.AF_UNIX, address5.sa_family);

                // Check getsockname(socket, null)
                if (Syscall.getsockname(so1, null) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }

                int so3;
                var remote = new SockaddrUn();
                if ((so3 = Syscall.accept(so1, remote)) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }
                try {
                    // Send and receive a few bytes
                    long ret;
                    var buffer1 = new byte[] { 42, 43, 44 };
                    ret         = Syscall.send(so2, buffer1, (ulong)buffer1.Length, 0);
                    if (ret < 0)
                    {
                        UnixMarshal.ThrowExceptionForLastError();
                    }

                    var buffer2 = new byte[1024];
                    ret         = Syscall.recv(so3, buffer2, (ulong)buffer2.Length, 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]);
                    }
                } finally {
                    if (Syscall.close(so3) < 0)
                    {
                        UnixMarshal.ThrowExceptionForLastError();
                    }
                }
            });
        }
Ejemplo n.º 16
0
        public void TestOFDLock()
        {
            int fd1 = Syscall.open(TempFolder + "/testfile", OpenFlags.O_RDWR | OpenFlags.O_CREAT | OpenFlags.O_EXCL, FilePermissions.DEFFILEMODE);

            if (fd1 < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }
            int fd2 = Syscall.open(TempFolder + "/testfile", OpenFlags.O_RDWR);

            if (fd2 < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }
            int fd3 = Syscall.open(TempFolder + "/testfile", OpenFlags.O_RDWR);

            if (fd3 < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }

            // Get read lock for first 100 bytes on fd1
            var flock1 = new Flock {
                l_type   = LockType.F_RDLCK,
                l_whence = SeekFlags.SEEK_SET,
                l_start  = 0,
                l_len    = 100,
            };

            if (Syscall.fcntl(fd1, FcntlCommand.F_OFD_SETLKW, ref flock1) < 0)
            {
                // Old kernels and non-linux systems should return EINVAL
                if (Stdlib.GetLastError() == Errno.EINVAL)
                {
                    Assert.Ignore("F_OFD_SETLKW does not seem to be supported.");
                }
                UnixMarshal.ThrowExceptionForLastError();
            }

            // Get read lock for first 100 bytes on fd2
            var flock2 = new Flock {
                l_type   = LockType.F_RDLCK,
                l_whence = SeekFlags.SEEK_SET,
                l_start  = 0,
                l_len    = 100,
            };

            if (Syscall.fcntl(fd2, FcntlCommand.F_OFD_SETLK, ref flock2) < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }

            // Get write lock for remaining bytes on fd1
            var flock3 = new Flock {
                l_type   = LockType.F_WRLCK,
                l_whence = SeekFlags.SEEK_SET,
                l_start  = 100,
                l_len    = 0,
            };

            if (Syscall.fcntl(fd1, FcntlCommand.F_OFD_SETLK, ref flock3) < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }

            // Close fd3, should not release lock
            if (Syscall.close(fd3) < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }

            // Get lock status for byte 150 from fd2
            var flock4 = new Flock {
                l_type   = LockType.F_RDLCK,
                l_whence = SeekFlags.SEEK_SET,
                l_start  = 150,
                l_len    = 1,
            };

            if (Syscall.fcntl(fd2, FcntlCommand.F_OFD_GETLK, ref flock4) < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }
            // There should be a conflicting write lock
            Assert.AreEqual(LockType.F_WRLCK, flock4.l_type);

            // Get write byte 0 on fd1, should fail with EAGAIN
            var flock5 = new Flock {
                l_type   = LockType.F_WRLCK,
                l_whence = SeekFlags.SEEK_SET,
                l_start  = 0,
                l_len    = 1,
            };
            var res = Syscall.fcntl(fd1, FcntlCommand.F_OFD_SETLK, ref flock5);

            Assert.AreEqual(-1, res);
            Assert.AreEqual(Errno.EAGAIN, Stdlib.GetLastError());

            if (Syscall.close(fd1) < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }
            if (Syscall.close(fd2) < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }
        }
Ejemplo n.º 17
0
        [ExpectedException(typeof(ArgumentOutOfRangeException))]           // IPPROTO_UDP not supported
#endif
        public void BindConnect()
        {
            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);


                // Connect so2 to so1
                var remoteAddress = new SockaddrIn {
                    sin_family = UnixAddressFamily.AF_INET,
                    sin_port   = Syscall.htons(port),
                    sin_addr   = new InAddr(127, 0, 0, 1),
                };
                if (Syscall.connect(so2, remoteAddress) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }

                // Verify peer address using getpeername()
                var address2 = new SockaddrIn();
                if (Syscall.getpeername(so2, address2) < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }
                Assert.AreEqual(address2.sa_family, UnixAddressFamily.AF_INET);
                Assert.AreEqual(remoteAddress.sin_port, address2.sin_port);
                Assert.AreEqual(remoteAddress.sin_addr, address2.sin_addr);

                // Send and receive a few bytes
                long ret;
                var buffer1 = new byte[] { 42, 43, 44 };
                ret         = Syscall.send(so2, buffer1, (ulong)buffer1.Length, 0);
                if (ret < 0)
                {
                    UnixMarshal.ThrowExceptionForLastError();
                }

                var buffer2 = new byte[1024];
                ret         = Syscall.recv(so1, buffer2, (ulong)buffer2.Length, 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]);
                }
            });
        }
Ejemplo n.º 18
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);
                }
            }
        }
Ejemplo n.º 19
0
    public static void Main(string[] args)
    {
        Bus conn;

        if (args.Length == 0)
        {
            conn = Bus.Session;
        }
        else
        {
            if (args[0] == "--session")
            {
                conn = Bus.Session;
            }
            else if (args[0] == "--system")
            {
                conn = Bus.System;
            }
            else
            {
                conn = Bus.Open(args[0]);
            }
        }

        IBus bus = conn.GetObject <IBus> ("org.freedesktop.DBus", new ObjectPath("/org/freedesktop/DBus"));

        Console.WriteLine(bus.ListNames().Length);

        var obj     = conn.GetObject <Interface> (Constants.BusName, Constants.ObjectPath);
        var obj2    = conn.GetObject <Interface2> (Constants.BusName, Constants.ObjectPath);
        var objIntr = conn.GetObject <Introspectable> (Constants.BusName, Constants.ObjectPath);

        obj.Ping();
        Console.WriteLine(obj.GetBytes(3).Length);

        Console.WriteLine("conn.UnixFDSupported = " + conn.UnixFDSupported);
        if (!conn.UnixFDSupported)
        {
            return;
        }

        using (var disposableList = new DisposableList()) {
            var res = obj.GetFD(disposableList, false);
            Console.WriteLine("Got FD:");
            Mono.Unix.Native.Stdlib.system("ls -l /proc/$PPID/fd/" + res.Handle);
        }
        using (var disposableList = new DisposableList()) {
            var res = obj.GetFDList(disposableList, false);
            Console.WriteLine("Got FDs:");
            foreach (var fd in res)
            {
                Mono.Unix.Native.Stdlib.system("ls -l /proc/$PPID/fd/" + fd.Handle);
            }
        }
        using (var disposableList = new DisposableList()) {
            var res = (UnixFD[])obj.GetFDListVariant(disposableList, false);
            Console.WriteLine("Got FDs as variant:");
            foreach (var fd in res)
            {
                Mono.Unix.Native.Stdlib.system("ls -l /proc/$PPID/fd/" + fd.Handle);
            }
        }

        using (var disposableList = new DisposableList()) {
            try {
                obj.GetFD(disposableList, true);
                throw new Exception("Expected an exception");
            } catch (Exception e) {
                if (!e.Message.Contains("Throwing an exception after creating a UnixFD object"))
                {
                    throw;
                }
            }
        }
        using (var disposableList = new DisposableList()) {
            try {
                obj.GetFDList(disposableList, true);
                throw new Exception("Expected an exception");
            } catch (Exception e) {
                if (!e.Message.Contains("Throwing an exception after creating a UnixFD object"))
                {
                    throw;
                }
            }
        }
        using (var disposableList = new DisposableList()) {
            try {
                obj.GetFDListVariant(disposableList, true);
                throw new Exception("Expected an exception");
            } catch (Exception e) {
                if (!e.Message.Contains("Throwing an exception after creating a UnixFD object"))
                {
                    throw;
                }
            }
        }

        // Check whether this leaks an FD
        obj.GetFD(null, false);
        obj.GetFDList(null, false);
        obj.GetFDListVariant(null, false);
        try { obj.GetFD(null, true); } catch {}
        try { obj.GetFDList(null, true); } catch {}
        try { obj.GetFDListVariant(null, true); } catch {}
        obj2.GetFD(false);
        obj2.GetFDList(false);
        obj2.GetFDListVariant(false);
        try { obj2.GetFD(true); } catch {}
        try { obj2.GetFDList(true); } catch {}
        try { obj2.GetFDListVariant(true); } catch {}

        var fd_ = Syscall.open("/dev/null", OpenFlags.O_RDWR, 0);

        if (fd_ < 0)
        {
            UnixMarshal.ThrowExceptionForLastError();
        }
        using (var fd = new UnixFD(fd_)) {
            obj.SendFD(fd);
            obj.SendFD(fd);
            obj.SendFDList(new UnixFD[] { fd, fd });
            obj.SendFDListVariant(new UnixFD[] { fd, fd });

            var impl  = new SignalsImpl();
            var spath = new ObjectPath("/mono_dbus_sharp_test/Signals");
            conn.Register(spath, impl);
            obj.RegisterSignalInterface(conn.UniqueName, spath);
            impl.CallGotFD(fd);
        }

        Console.WriteLine(objIntr.Introspect().Length);

        obj.ListOpenFDs();
        Console.WriteLine("Open FDs:");
        Mono.Unix.Native.Stdlib.system("ls -l /proc/$PPID/fd/");
    }