Serenity Operating System
at master 180 lines 5.8 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Assertions.h> 8#include <bits/pthread_cancel.h> 9#include <errno.h> 10#include <stdio.h> 11#include <string.h> 12#include <sys/socket.h> 13#include <sys/uio.h> 14#include <syscall.h> 15 16extern "C" { 17 18// https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html 19int socket(int domain, int type, int protocol) 20{ 21 int rc = syscall(SC_socket, domain, type, protocol); 22 __RETURN_WITH_ERRNO(rc, rc, -1); 23} 24 25// https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html 26int bind(int sockfd, sockaddr const* addr, socklen_t addrlen) 27{ 28 int rc = syscall(SC_bind, sockfd, addr, addrlen); 29 __RETURN_WITH_ERRNO(rc, rc, -1); 30} 31 32// https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html 33int listen(int sockfd, int backlog) 34{ 35 int rc = syscall(SC_listen, sockfd, backlog); 36 __RETURN_WITH_ERRNO(rc, rc, -1); 37} 38 39// https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html 40int accept(int sockfd, sockaddr* addr, socklen_t* addrlen) 41{ 42 __pthread_maybe_cancel(); 43 44 return accept4(sockfd, addr, addrlen, 0); 45} 46 47int accept4(int sockfd, sockaddr* addr, socklen_t* addrlen, int flags) 48{ 49 Syscall::SC_accept4_params params { addr, addrlen, sockfd, flags }; 50 int rc = syscall(SC_accept4, &params); 51 __RETURN_WITH_ERRNO(rc, rc, -1); 52} 53 54// https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html 55int connect(int sockfd, sockaddr const* addr, socklen_t addrlen) 56{ 57 __pthread_maybe_cancel(); 58 59 int rc = syscall(SC_connect, sockfd, addr, addrlen); 60 __RETURN_WITH_ERRNO(rc, rc, -1); 61} 62 63// https://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html 64int shutdown(int sockfd, int how) 65{ 66 int rc = syscall(SC_shutdown, sockfd, how); 67 __RETURN_WITH_ERRNO(rc, rc, -1); 68} 69 70// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html 71ssize_t sendmsg(int sockfd, const struct msghdr* msg, int flags) 72{ 73 __pthread_maybe_cancel(); 74 75 int rc = syscall(SC_sendmsg, sockfd, msg, flags); 76 __RETURN_WITH_ERRNO(rc, rc, -1); 77} 78 79// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html 80ssize_t sendto(int sockfd, void const* data, size_t data_length, int flags, const struct sockaddr* addr, socklen_t addr_length) 81{ 82 iovec iov = { const_cast<void*>(data), data_length }; 83 msghdr msg = { const_cast<struct sockaddr*>(addr), addr_length, &iov, 1, nullptr, 0, 0 }; 84 return sendmsg(sockfd, &msg, flags); 85} 86 87// https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html 88ssize_t send(int sockfd, void const* data, size_t data_length, int flags) 89{ 90 return sendto(sockfd, data, data_length, flags, nullptr, 0); 91} 92 93// https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html 94ssize_t recvmsg(int sockfd, struct msghdr* msg, int flags) 95{ 96 __pthread_maybe_cancel(); 97 98 int rc = syscall(SC_recvmsg, sockfd, msg, flags); 99 __RETURN_WITH_ERRNO(rc, rc, -1); 100} 101 102// https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html 103ssize_t recvfrom(int sockfd, void* buffer, size_t buffer_length, int flags, struct sockaddr* addr, socklen_t* addr_length) 104{ 105 __pthread_maybe_cancel(); 106 107 if (!addr_length && addr) { 108 errno = EINVAL; 109 return -1; 110 } 111 112 sockaddr_storage internal_addr; 113 iovec iov = { buffer, buffer_length }; 114 msghdr msg = { addr ? &internal_addr : nullptr, addr ? (socklen_t)sizeof(internal_addr) : 0, &iov, 1, nullptr, 0, 0 }; 115 ssize_t rc = recvmsg(sockfd, &msg, flags); 116 if (rc >= 0 && addr) { 117 memcpy(addr, &internal_addr, min(*addr_length, msg.msg_namelen)); 118 *addr_length = msg.msg_namelen; 119 } 120 return rc; 121} 122 123// https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html 124ssize_t recv(int sockfd, void* buffer, size_t buffer_length, int flags) 125{ 126 return recvfrom(sockfd, buffer, buffer_length, flags, nullptr, nullptr); 127} 128 129// https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html 130int getsockopt(int sockfd, int level, int option, void* value, socklen_t* value_size) 131{ 132 Syscall::SC_getsockopt_params params { sockfd, level, option, value, value_size }; 133 int rc = syscall(SC_getsockopt, &params); 134 __RETURN_WITH_ERRNO(rc, rc, -1); 135} 136 137// https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html 138int setsockopt(int sockfd, int level, int option, void const* value, socklen_t value_size) 139{ 140 Syscall::SC_setsockopt_params params { value, sockfd, level, option, value_size }; 141 int rc = syscall(SC_setsockopt, &params); 142 __RETURN_WITH_ERRNO(rc, rc, -1); 143} 144 145// https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html 146int getsockname(int sockfd, struct sockaddr* addr, socklen_t* addrlen) 147{ 148 Syscall::SC_getsockname_params params { sockfd, addr, addrlen }; 149 int rc = syscall(SC_getsockname, &params); 150 __RETURN_WITH_ERRNO(rc, rc, -1); 151} 152 153// https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html 154int getpeername(int sockfd, struct sockaddr* addr, socklen_t* addrlen) 155{ 156 Syscall::SC_getpeername_params params { sockfd, addr, addrlen }; 157 int rc = syscall(SC_getpeername, &params); 158 __RETURN_WITH_ERRNO(rc, rc, -1); 159} 160 161// https://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html 162int socketpair(int domain, int type, int protocol, int sv[2]) 163{ 164 Syscall::SC_socketpair_params params { domain, type, protocol, sv }; 165 int rc = syscall(SC_socketpair, &params); 166 __RETURN_WITH_ERRNO(rc, rc, -1); 167} 168 169int sendfd(int sockfd, int fd) 170{ 171 int rc = syscall(SC_sendfd, sockfd, fd); 172 __RETURN_WITH_ERRNO(rc, rc, -1); 173} 174 175int recvfd(int sockfd, int options) 176{ 177 int rc = syscall(SC_recvfd, sockfd, options); 178 __RETURN_WITH_ERRNO(rc, rc, -1); 179} 180}