socket.cpp 5.7 KB

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