mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-05-02 17:28:48 +00:00
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.
This commit is contained in:
parent
f008156dbf
commit
ae470ec955
Notes:
sideshowbarker
2024-07-19 14:00:00 +09:00
Author: https://github.com/awesomekling
Commit: ae470ec955
11 changed files with 73 additions and 9 deletions
|
@ -46,12 +46,28 @@ IPv4Socket::~IPv4Socket()
|
||||||
all_sockets().resource().remove(this);
|
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.
|
// FIXME: Look into what fallback behavior we should have here.
|
||||||
if (*address_size != sizeof(sockaddr_in))
|
if (*address_size < sizeof(sockaddr_in))
|
||||||
return false;
|
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);
|
*address_size = sizeof(sockaddr_in);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,8 @@ public:
|
||||||
|
|
||||||
virtual KResult bind(const sockaddr*, socklen_t) override;
|
virtual KResult bind(const sockaddr*, socklen_t) override;
|
||||||
virtual KResult connect(FileDescriptor&, const sockaddr*, socklen_t, ShouldBlock = ShouldBlock::Yes) 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 attach(FileDescriptor&) override;
|
||||||
virtual void detach(FileDescriptor&) override;
|
virtual void detach(FileDescriptor&) override;
|
||||||
virtual bool can_read(FileDescriptor&) const override;
|
virtual bool can_read(FileDescriptor&) const override;
|
||||||
|
|
|
@ -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.
|
// FIXME: Look into what fallback behavior we should have here.
|
||||||
if (*address_size != sizeof(sockaddr_un))
|
if (*address_size != sizeof(sockaddr_un))
|
||||||
|
@ -34,6 +34,11 @@ bool LocalSocket::get_address(sockaddr* address, socklen_t* address_size)
|
||||||
return true;
|
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)
|
KResult LocalSocket::bind(const sockaddr* address, socklen_t address_size)
|
||||||
{
|
{
|
||||||
ASSERT(!is_connected());
|
ASSERT(!is_connected());
|
||||||
|
|
|
@ -12,7 +12,8 @@ public:
|
||||||
|
|
||||||
virtual KResult bind(const sockaddr*, socklen_t) override;
|
virtual KResult bind(const sockaddr*, socklen_t) override;
|
||||||
virtual KResult connect(FileDescriptor&, const sockaddr*, socklen_t, ShouldBlock = ShouldBlock::Yes) 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 attach(FileDescriptor&) override;
|
||||||
virtual void detach(FileDescriptor&) override;
|
virtual void detach(FileDescriptor&) override;
|
||||||
virtual bool can_read(FileDescriptor&) const override;
|
virtual bool can_read(FileDescriptor&) const override;
|
||||||
|
|
|
@ -30,7 +30,8 @@ public:
|
||||||
|
|
||||||
virtual KResult bind(const sockaddr*, socklen_t) = 0;
|
virtual KResult bind(const sockaddr*, socklen_t) = 0;
|
||||||
virtual KResult connect(FileDescriptor&, const sockaddr*, socklen_t, ShouldBlock) = 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_local() const { return false; }
|
||||||
virtual bool is_ipv4() const { return false; }
|
virtual bool is_ipv4() const { return false; }
|
||||||
virtual void attach(FileDescriptor&) = 0;
|
virtual void attach(FileDescriptor&) = 0;
|
||||||
|
|
|
@ -2120,7 +2120,7 @@ int Process::sys$accept(int accepting_socket_fd, sockaddr* address, socklen_t* a
|
||||||
}
|
}
|
||||||
auto accepted_socket = socket.accept();
|
auto accepted_socket = socket.accept();
|
||||||
ASSERT(accepted_socket);
|
ASSERT(accepted_socket);
|
||||||
bool success = accepted_socket->get_address(address, address_size);
|
bool success = accepted_socket->get_local_address(address, address_size);
|
||||||
ASSERT(success);
|
ASSERT(success);
|
||||||
auto accepted_socket_descriptor = FileDescriptor::create(move(accepted_socket), SocketRole::Accepted);
|
auto accepted_socket_descriptor = FileDescriptor::create(move(accepted_socket), SocketRole::Accepted);
|
||||||
// NOTE: The accepted socket inherits fd flags from the accepting socket.
|
// 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;
|
return -ENOTSOCK;
|
||||||
|
|
||||||
auto& socket = *descriptor->socket();
|
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 -EINVAL; // FIXME: Should this be another error? I'm not sure.
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -176,6 +176,7 @@ public:
|
||||||
int sys$getsockopt(const Syscall::SC_getsockopt_params*);
|
int sys$getsockopt(const Syscall::SC_getsockopt_params*);
|
||||||
int sys$setsockopt(const Syscall::SC_setsockopt_params*);
|
int sys$setsockopt(const Syscall::SC_setsockopt_params*);
|
||||||
int sys$getsockname(int sockfd, sockaddr* addr, socklen_t* addrlen);
|
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$restore_signal_mask(dword mask);
|
||||||
int sys$create_thread(int(*)(void*), void*);
|
int sys$create_thread(int(*)(void*), void*);
|
||||||
void sys$exit_thread(int code);
|
void sys$exit_thread(int code);
|
||||||
|
|
|
@ -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);
|
return current->process().sys$writev((int)arg1, (const struct iovec*)arg2, (int)arg3);
|
||||||
case Syscall::SC_getsockname:
|
case Syscall::SC_getsockname:
|
||||||
return current->process().sys$getsockname((int)arg1, (sockaddr*)arg2, (socklen_t*)arg3);
|
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:
|
default:
|
||||||
kprintf("<%u> int0x82: Unknown function %u requested {%x, %x, %x}\n", current->process().pid(), function, arg1, arg2, arg3);
|
kprintf("<%u> int0x82: Unknown function %u requested {%x, %x, %x}\n", current->process().pid(), function, arg1, arg2, arg3);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
__ENUMERATE_SYSCALL(writev) \
|
__ENUMERATE_SYSCALL(writev) \
|
||||||
__ENUMERATE_SYSCALL(beep) \
|
__ENUMERATE_SYSCALL(beep) \
|
||||||
__ENUMERATE_SYSCALL(getsockname) \
|
__ENUMERATE_SYSCALL(getsockname) \
|
||||||
|
__ENUMERATE_SYSCALL(getpeername) \
|
||||||
|
|
||||||
|
|
||||||
namespace Syscall {
|
namespace Syscall {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <Kernel/Syscall.h>
|
#include <Kernel/Syscall.h>
|
||||||
|
#include <AK/Assertions.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
@ -78,4 +80,10 @@ int getsockname(int sockfd, struct sockaddr* addr, socklen_t* addrlen)
|
||||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getpeername(int sockfd, struct sockaddr* addr, socklen_t* addrlen)
|
||||||
|
{
|
||||||
|
int rc = syscall(SC_getpeername, sockfd, addr, addrlen);
|
||||||
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ struct sockaddr_in {
|
||||||
|
|
||||||
#define SO_RCVTIMEO 1
|
#define SO_RCVTIMEO 1
|
||||||
#define SO_SNDTIMEO 2
|
#define SO_SNDTIMEO 2
|
||||||
|
#define SO_KEEPALIVE 3
|
||||||
|
|
||||||
int socket(int domain, int type, int protocol);
|
int socket(int domain, int type, int protocol);
|
||||||
int bind(int sockfd, const struct sockaddr* addr, socklen_t);
|
int bind(int sockfd, const struct sockaddr* addr, socklen_t);
|
||||||
|
@ -68,6 +69,7 @@ ssize_t recvfrom(int sockfd, void*, size_t, int flags, struct sockaddr*, socklen
|
||||||
int getsockopt(int sockfd, int level, int option, void*, socklen_t*);
|
int getsockopt(int sockfd, int level, int option, void*, socklen_t*);
|
||||||
int setsockopt(int sockfd, int level, int option, const void*, socklen_t);
|
int setsockopt(int sockfd, int level, int option, const void*, socklen_t);
|
||||||
int getsockname(int sockfd, struct sockaddr*, socklen_t*);
|
int getsockname(int sockfd, struct sockaddr*, socklen_t*);
|
||||||
|
int getpeername(int sockfd, struct sockaddr*, socklen_t*);
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue