diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-02-14 14:38:30 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-02-14 14:38:30 +0100 |
commit | 77177dbb767259a6135347f88a2bf78cc4ea72bd (patch) | |
tree | 6e932c4db5ca6c44919e0da844eccbcb1c256316 | |
parent | 2f35e54f80a3e94319ee4157e6d8be666a303eaf (diff) | |
download | serenity-77177dbb767259a6135347f88a2bf78cc4ea72bd.zip |
Kernel: Begin fleshing out bind() syscall.
-rw-r--r-- | Kernel/LocalSocket.cpp | 28 | ||||
-rw-r--r-- | Kernel/LocalSocket.h | 2 | ||||
-rw-r--r-- | Kernel/Process.cpp | 15 | ||||
-rw-r--r-- | Kernel/Socket.h | 3 | ||||
-rw-r--r-- | Kernel/UnixTypes.h | 1 | ||||
-rw-r--r-- | Kernel/VirtualFileSystem.cpp | 11 | ||||
-rw-r--r-- | LibC/errno_numbers.h | 2 |
7 files changed, 57 insertions, 5 deletions
diff --git a/Kernel/LocalSocket.cpp b/Kernel/LocalSocket.cpp index 1fbf633223..fc6ea87b3b 100644 --- a/Kernel/LocalSocket.cpp +++ b/Kernel/LocalSocket.cpp @@ -1,6 +1,8 @@ #include <Kernel/LocalSocket.h> #include <Kernel/UnixTypes.h> #include <Kernel/Process.h> +#include <Kernel/VirtualFileSystem.h> +#include <LibC/errno_numbers.h> RetainPtr<LocalSocket> LocalSocket::create(int type) { @@ -17,3 +19,29 @@ LocalSocket::~LocalSocket() { } +bool LocalSocket::bind(const sockaddr* address, socklen_t address_size, int& error) +{ + if (address_size != sizeof(sockaddr_un)) { + error = -EINVAL; + return false; + } + + if (address->sa_family != AF_LOCAL) { + error = -EINVAL; + return false; + } + + const sockaddr_un& local_address = *reinterpret_cast<const sockaddr_un*>(address); + char safe_address[sizeof(local_address.sun_path) + 1]; + memcpy(safe_address, local_address.sun_path, sizeof(local_address.sun_path)); + + kprintf("%s(%u) LocalSocket{%p} bind(%s)\n", current->name().characters(), current->pid(), safe_address); + + auto descriptor = VFS::the().open(safe_address, error, O_CREAT | O_EXCL, S_IFSOCK | 0666, *current->cwd_inode()); + if (!descriptor) { + if (error == -EEXIST) + error = -EADDRINUSE; + return error; + } + return true; +} diff --git a/Kernel/LocalSocket.h b/Kernel/LocalSocket.h index 31a62bb28c..916de48ba5 100644 --- a/Kernel/LocalSocket.h +++ b/Kernel/LocalSocket.h @@ -8,6 +8,8 @@ public: static RetainPtr<LocalSocket> create(int type); virtual ~LocalSocket() override; + virtual bool bind(const sockaddr*, socklen_t, int& error) override; + private: explicit LocalSocket(int type); diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index ea5e791e5b..af9fcfc921 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -2262,9 +2262,20 @@ int Process::sys$socket(int domain, int type, int protocol) return fd; } -int Process::sys$bind(int sockfd, const sockaddr* addr, socklen_t) +int Process::sys$bind(int sockfd, const sockaddr* address, socklen_t address_length) { - return -ENOTIMPL; + if (!validate_read(address, address_length)) + return -EFAULT; + auto* descriptor = file_descriptor(sockfd); + if (!descriptor) + return -EBADF; + if (!descriptor->is_socket()) + return -ENOTSOCK; + auto& socket = *descriptor->socket(); + int error; + if (!socket.bind(address, address_length, error)) + return error; + return 0; } int Process::sys$listen(int sockfd, int backlog) diff --git a/Kernel/Socket.h b/Kernel/Socket.h index c44ca5da21..a6c8809f36 100644 --- a/Kernel/Socket.h +++ b/Kernel/Socket.h @@ -2,6 +2,7 @@ #include <AK/Retainable.h> #include <AK/RetainPtr.h> +#include <Kernel/UnixTypes.h> class Socket : public Retainable<Socket> { public: @@ -12,6 +13,8 @@ public: int type() const { return m_type; } int protocol() const { return m_protocol; } + virtual bool bind(const sockaddr*, socklen_t, int& error) = 0; + protected: Socket(int domain, int type, int protocol); diff --git a/Kernel/UnixTypes.h b/Kernel/UnixTypes.h index 3137234d59..d8302f326a 100644 --- a/Kernel/UnixTypes.h +++ b/Kernel/UnixTypes.h @@ -314,6 +314,7 @@ struct sockaddr { char sa_data[14]; }; +#define S_IFSOCK 0140000 #define UNIX_PATH_MAX 108 struct sockaddr_un { diff --git a/Kernel/VirtualFileSystem.cpp b/Kernel/VirtualFileSystem.cpp index ff630ed572..ed6f060de3 100644 --- a/Kernel/VirtualFileSystem.cpp +++ b/Kernel/VirtualFileSystem.cpp @@ -134,11 +134,16 @@ RetainPtr<FileDescriptor> VFS::open(const String& path, int& error, int options, { auto inode_id = resolve_path(path, base.identifier(), error, options); auto inode = get_inode(inode_id); - if (!inode) { - if (options & O_CREAT) + if (options & O_CREAT) { + if (!inode) return create(path, error, options, mode, base); - return nullptr; + else if (options & O_EXCL) { + error = -EEXIST; + return nullptr; + } } + if (!inode) + return nullptr; auto metadata = inode->metadata(); if (!(options & O_DONT_OPEN_DEVICE) && metadata.is_character_device()) { auto it = m_character_devices.find(encoded_device(metadata.major_device, metadata.minor_device)); diff --git a/LibC/errno_numbers.h b/LibC/errno_numbers.h index c43c863dc5..476079e927 100644 --- a/LibC/errno_numbers.h +++ b/LibC/errno_numbers.h @@ -42,6 +42,8 @@ __ERROR(ENOSYS, "No such syscall") \ __ERROR(ENOTIMPL, "Not implemented") \ __ERROR(EAFNOSUPPORT, "Address family not supported") \ + __ERROR(ENOTSOCK, "Not a socket") \ + __ERROR(EADDRINUSE, "Address in use") \ __ERROR(EWHYTHO, "Failed without setting an error code (Bug!)") \ __ERROR(EBADWINDOW, "Bad window ID") \ __ERROR(EBADBACKING, "Bad backing store ID") \ |