diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 5bb934088f98e3..bf4e0ed0dc8974 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -2217,6 +2217,31 @@ ssize_t Process::sys$recvfrom(const Syscall::SC_recvfrom_params* params) return socket.recvfrom(*descriptor, buffer, buffer_length, flags, addr, addr_length); } +int Process::sys$getsockname(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_address(addr, addrlen)) + return -EINVAL; // FIXME: Should this be another error? I'm not sure. + + return 0; +} + int Process::sys$getsockopt(const Syscall::SC_getsockopt_params* params) { if (!validate_read_typed(params)) diff --git a/Kernel/Process.h b/Kernel/Process.h index 69144b35b04919..7f2f1b5a915d99 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -175,6 +175,7 @@ class Process : public InlineLinkedListNode, public Weakable { ssize_t sys$recvfrom(const Syscall::SC_recvfrom_params*); 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$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 0c083f7a322b26..131fbc647e4f75 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -272,6 +272,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2, return current->process().sys$mknod((const char*)arg1, (mode_t)arg2, (dev_t)arg3); case Syscall::SC_writev: 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); 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 5f66bb1df3a6c7..7acd3124bdd437 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -104,6 +104,7 @@ __ENUMERATE_SYSCALL(mknod) \ __ENUMERATE_SYSCALL(writev) \ __ENUMERATE_SYSCALL(beep) \ + __ENUMERATE_SYSCALL(getsockname) \ namespace Syscall { diff --git a/LibC/sys/socket.cpp b/LibC/sys/socket.cpp index e92f3d9744bcd7..c177ecd1dfb9fc 100644 --- a/LibC/sys/socket.cpp +++ b/LibC/sys/socket.cpp @@ -72,4 +72,10 @@ int setsockopt(int sockfd, int level, int option, const void* value, socklen_t v __RETURN_WITH_ERRNO(rc, rc, -1); } +int getsockname(int sockfd, struct sockaddr* addr, socklen_t* addrlen) +{ + int rc = syscall(SC_getsockname, sockfd, addr, addrlen); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + } diff --git a/LibC/sys/socket.h b/LibC/sys/socket.h index a1b8b0d4b82896..4e4f3227bf9fd9 100644 --- a/LibC/sys/socket.h +++ b/LibC/sys/socket.h @@ -65,6 +65,7 @@ ssize_t recv(int sockfd, void*, size_t, int flags); ssize_t recvfrom(int sockfd, void*, size_t, int flags, struct sockaddr*, 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 getsockname(int sockfd, struct sockaddr*, socklen_t*); __END_DECLS