summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-05-20 20:33:03 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-05-20 20:33:03 +0200
commitae470ec9558e5903ff68bd3cf95e1355e5a13c1c (patch)
treeb80d21b27d1c1d7fe62d0f77db3766b07c5a2008 /Kernel
parentf008156dbf30a892827f3b6bf7203680533b2eb9 (diff)
downloadserenity-ae470ec9558e5903ff68bd3cf95e1355e5a13c1c.zip
Kernel: Add getpeername() syscall, and fix getsockname() behavior.
We were copying the raw IPv4 addresses into the wrong part of sockaddr_in, and we didn't set sa_family or sa_port.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Net/IPv4Socket.cpp22
-rw-r--r--Kernel/Net/IPv4Socket.h3
-rw-r--r--Kernel/Net/LocalSocket.cpp7
-rw-r--r--Kernel/Net/LocalSocket.h3
-rw-r--r--Kernel/Net/Socket.h3
-rw-r--r--Kernel/Process.cpp30
-rw-r--r--Kernel/Process.h1
-rw-r--r--Kernel/Syscall.cpp2
-rw-r--r--Kernel/Syscall.h1
9 files changed, 63 insertions, 9 deletions
diff --git a/Kernel/Net/IPv4Socket.cpp b/Kernel/Net/IPv4Socket.cpp
index f6b4b96ed6..681674ba61 100644
--- a/Kernel/Net/IPv4Socket.cpp
+++ b/Kernel/Net/IPv4Socket.cpp
@@ -46,12 +46,28 @@ IPv4Socket::~IPv4Socket()
all_sockets().resource().remove(this);
}
-bool IPv4Socket::get_address(sockaddr* address, socklen_t* address_size)
+bool IPv4Socket::get_local_address(sockaddr* address, socklen_t* address_size)
{
// FIXME: Look into what fallback behavior we should have here.
- if (*address_size != sizeof(sockaddr_in))
+ if (*address_size < sizeof(sockaddr_in))
return false;
- memcpy(address, &m_peer_address, sizeof(sockaddr_in));
+ auto& ia = (sockaddr_in&)*address;
+ ia.sin_family = AF_INET;
+ ia.sin_port = m_local_port;
+ memcpy(&ia.sin_addr, &m_local_address, sizeof(IPv4Address));
+ *address_size = sizeof(sockaddr_in);
+ return true;
+}
+
+bool IPv4Socket::get_peer_address(sockaddr* address, socklen_t* address_size)
+{
+ // FIXME: Look into what fallback behavior we should have here.
+ if (*address_size < sizeof(sockaddr_in))
+ return false;
+ auto& ia = (sockaddr_in&)*address;
+ ia.sin_family = AF_INET;
+ ia.sin_port = m_peer_port;
+ memcpy(&ia.sin_addr, &m_peer_address, sizeof(IPv4Address));
*address_size = sizeof(sockaddr_in);
return true;
}
diff --git a/Kernel/Net/IPv4Socket.h b/Kernel/Net/IPv4Socket.h
index 3d7b145293..33b4f9d420 100644
--- a/Kernel/Net/IPv4Socket.h
+++ b/Kernel/Net/IPv4Socket.h
@@ -22,7 +22,8 @@ public:
virtual KResult bind(const sockaddr*, socklen_t) override;
virtual KResult connect(FileDescriptor&, const sockaddr*, socklen_t, ShouldBlock = ShouldBlock::Yes) override;
- virtual bool get_address(sockaddr*, socklen_t*) override;
+ virtual bool get_local_address(sockaddr*, socklen_t*) override;
+ virtual bool get_peer_address(sockaddr*, socklen_t*) override;
virtual void attach(FileDescriptor&) override;
virtual void detach(FileDescriptor&) override;
virtual bool can_read(FileDescriptor&) const override;
diff --git a/Kernel/Net/LocalSocket.cpp b/Kernel/Net/LocalSocket.cpp
index c6cf763b2f..17ee5fc2cf 100644
--- a/Kernel/Net/LocalSocket.cpp
+++ b/Kernel/Net/LocalSocket.cpp
@@ -24,7 +24,7 @@ LocalSocket::~LocalSocket()
{
}
-bool LocalSocket::get_address(sockaddr* address, socklen_t* address_size)
+bool LocalSocket::get_local_address(sockaddr* address, socklen_t* address_size)
{
// FIXME: Look into what fallback behavior we should have here.
if (*address_size != sizeof(sockaddr_un))
@@ -34,6 +34,11 @@ bool LocalSocket::get_address(sockaddr* address, socklen_t* address_size)
return true;
}
+bool LocalSocket::get_peer_address(sockaddr* address, socklen_t* address_size)
+{
+ return get_local_address(address, address_size);
+}
+
KResult LocalSocket::bind(const sockaddr* address, socklen_t address_size)
{
ASSERT(!is_connected());
diff --git a/Kernel/Net/LocalSocket.h b/Kernel/Net/LocalSocket.h
index 81b902a982..db481912f2 100644
--- a/Kernel/Net/LocalSocket.h
+++ b/Kernel/Net/LocalSocket.h
@@ -12,7 +12,8 @@ public:
virtual KResult bind(const sockaddr*, socklen_t) override;
virtual KResult connect(FileDescriptor&, const sockaddr*, socklen_t, ShouldBlock = ShouldBlock::Yes) override;
- virtual bool get_address(sockaddr*, socklen_t*) override;
+ virtual bool get_local_address(sockaddr*, socklen_t*) override;
+ virtual bool get_peer_address(sockaddr*, socklen_t*) override;
virtual void attach(FileDescriptor&) override;
virtual void detach(FileDescriptor&) override;
virtual bool can_read(FileDescriptor&) const override;
diff --git a/Kernel/Net/Socket.h b/Kernel/Net/Socket.h
index 151e250268..0fb9544cbb 100644
--- a/Kernel/Net/Socket.h
+++ b/Kernel/Net/Socket.h
@@ -30,7 +30,8 @@ public:
virtual KResult bind(const sockaddr*, socklen_t) = 0;
virtual KResult connect(FileDescriptor&, const sockaddr*, socklen_t, ShouldBlock) = 0;
- virtual bool get_address(sockaddr*, socklen_t*) = 0;
+ virtual bool get_local_address(sockaddr*, socklen_t*) = 0;
+ virtual bool get_peer_address(sockaddr*, socklen_t*) = 0;
virtual bool is_local() const { return false; }
virtual bool is_ipv4() const { return false; }
virtual void attach(FileDescriptor&) = 0;
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index cae1d20648..80de78b8a5 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -2120,7 +2120,7 @@ int Process::sys$accept(int accepting_socket_fd, sockaddr* address, socklen_t* a
}
auto accepted_socket = socket.accept();
ASSERT(accepted_socket);
- bool success = accepted_socket->get_address(address, address_size);
+ bool success = accepted_socket->get_local_address(address, address_size);
ASSERT(success);
auto accepted_socket_descriptor = FileDescriptor::create(move(accepted_socket), SocketRole::Accepted);
// NOTE: The accepted socket inherits fd flags from the accepting socket.
@@ -2240,7 +2240,33 @@ int Process::sys$getsockname(int sockfd, sockaddr* addr, socklen_t* addrlen)
return -ENOTSOCK;
auto& socket = *descriptor->socket();
- if (!socket.get_address(addr, addrlen))
+ if (!socket.get_local_address(addr, addrlen))
+ return -EINVAL; // FIXME: Should this be another error? I'm not sure.
+
+ return 0;
+}
+
+int Process::sys$getpeername(int sockfd, sockaddr* addr, socklen_t* addrlen)
+{
+ if (!validate_read_typed(addrlen))
+ return -EFAULT;
+
+ if (*addrlen <= 0)
+ return -EINVAL;
+
+ if (!validate_write(addr, *addrlen))
+ return -EFAULT;
+
+ auto* descriptor = file_descriptor(sockfd);
+ if (!descriptor)
+ return -EBADF;
+
+ if (!descriptor->is_socket())
+ return -ENOTSOCK;
+
+ auto& socket = *descriptor->socket();
+
+ if (!socket.get_peer_address(addr, addrlen))
return -EINVAL; // FIXME: Should this be another error? I'm not sure.
return 0;
diff --git a/Kernel/Process.h b/Kernel/Process.h
index f0f6fb246f..ff3d4e5e5c 100644
--- a/Kernel/Process.h
+++ b/Kernel/Process.h
@@ -176,6 +176,7 @@ public:
int sys$getsockopt(const Syscall::SC_getsockopt_params*);
int sys$setsockopt(const Syscall::SC_setsockopt_params*);
int sys$getsockname(int sockfd, sockaddr* addr, socklen_t* addrlen);
+ int sys$getpeername(int sockfd, sockaddr* addr, socklen_t* addrlen);
int sys$restore_signal_mask(dword mask);
int sys$create_thread(int(*)(void*), void*);
void sys$exit_thread(int code);
diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp
index 131fbc647e..338252f632 100644
--- a/Kernel/Syscall.cpp
+++ b/Kernel/Syscall.cpp
@@ -274,6 +274,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
return current->process().sys$writev((int)arg1, (const struct iovec*)arg2, (int)arg3);
case Syscall::SC_getsockname:
return current->process().sys$getsockname((int)arg1, (sockaddr*)arg2, (socklen_t*)arg3);
+ case Syscall::SC_getpeername:
+ return current->process().sys$getpeername((int)arg1, (sockaddr*)arg2, (socklen_t*)arg3);
default:
kprintf("<%u> int0x82: Unknown function %u requested {%x, %x, %x}\n", current->process().pid(), function, arg1, arg2, arg3);
break;
diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h
index 7acd3124bd..2d093f6a74 100644
--- a/Kernel/Syscall.h
+++ b/Kernel/Syscall.h
@@ -105,6 +105,7 @@
__ENUMERATE_SYSCALL(writev) \
__ENUMERATE_SYSCALL(beep) \
__ENUMERATE_SYSCALL(getsockname) \
+ __ENUMERATE_SYSCALL(getpeername) \
namespace Syscall {