2#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 1
3#include "pedigree/kernel/LockGuard.h"
4#include "pedigree/kernel/process/Thread.h"
5#include "pedigree/kernel/processor/Processor.h"
6#include "pedigree/kernel/processor/ProcessorInformation.h"
7#include "pedigree/kernel/syscallError.h"
8#include "pedigree/kernel/utilities/utility.h"
13#include "FileDescriptor.h"
14#include "net-syscalls.h"
15#include "network-namespace.h"
16#include <netinet/in.h>
17#include <netinet/tcp.h>
21constexpr uint32_t Loopback = 0x7f000001;
22constexpr socklen_t EndpointLength = offsetof(sockaddr_un, sun_path) + 16;
24void endpoint(sockaddr_storage& output,
int type, uint32_t address, uint16_t port, uint64_t token) {
25 ByteSet(&output, 0,
sizeof(output));
26 auto* local =
reinterpret_cast<sockaddr_un*
>(&output);
27 local->sun_family = AF_UNIX;
28 local->sun_path[1] = type;
29 MemoryCopy(local->sun_path + 2, &address, 4);
30 MemoryCopy(local->sun_path + 6, &port, 2);
31 MemoryCopy(local->sun_path + 8, &token, 8);
33sockaddr_in decode(
const sockaddr_storage& address, socklen_t length) {
34 sockaddr_in result = {};
35 result.sin_family = AF_INET;
36 if (length >= EndpointLength) {
37 const auto* local =
reinterpret_cast<const sockaddr_un*
>(&address);
40 MemoryCopy(&ip, local->sun_path + 2, 4);
41 MemoryCopy(&port, local->sun_path + 6, 2);
42 result.sin_addr.s_addr = HOST_TO_BIG32(ip);
43 result.sin_port = HOST_TO_BIG16(port);
47void copyAddress(
const sockaddr_in& source, sockaddr_storage* destination, socklen_t* length) {
49 MemoryCopy(destination, &source, *length <
sizeof(source) ? *length : sizeof(source));
51 *length =
sizeof(source);
53bool internetAddress(
const sockaddr_storage* input, socklen_t length, uint32_t& ip,
55 if (!input || length <
sizeof(sockaddr_in) || input->ss_family != AF_INET) {
59 const auto* address =
reinterpret_cast<const sockaddr_in*
>(input);
60 ip = BIG_TO_HOST32(address->sin_addr.s_addr);
61 port = BIG_TO_HOST16(address->sin_port);
67 LoopbackSocket(
int type,
int protocol,
const NetworkNamespaceRef& space,
bool accepted =
false)
69 m_NetworkNamespace = space;
71 ~LoopbackSocket()
override {
75 if ((getType() != SOCK_STREAM && getType() != SOCK_DGRAM) ||
77 getProtocol() != (getType() == SOCK_STREAM ? IPPROTO_TCP : IPPROTO_UDP))) {
78 syscallError(EPROTONOSUPPORT);
83 int bind(
const sockaddr_storage* address, socklen_t length)
override {
86 if (!internetAddress(address, length, ip, port)) {
94 if (m_Token || m_Accepted) {
98 return bindLocked(ip, port);
100 int listen(
int backlog)
override {
101 if (!ensureBound(0)) {
106 int connect(
const sockaddr_storage* address, socklen_t length)
override {
107 sockaddr_storage destination;
108 if (!destinationEndpoint(address, length, destination) || !ensureBound(Loopback)) {
111 const int result = UnixSocketSyscalls::connect(&destination, EndpointLength);
114 MemoryCopy(&m_Peer, address,
sizeof(m_Peer));
115 if (!m_Peer.sin_addr.s_addr) {
116 m_Peer.sin_addr.s_addr = HOST_TO_BIG32(Loopback);
124 syscallError(EOPNOTSUPP);
127 if (!m_NetworkNamespace->usable()) {
128 syscallError(ENETUNREACH);
131 if (!ensureBound(Loopback)) {
134 sockaddr_storage destination;
137 if (!destinationEndpoint(
reinterpret_cast<const sockaddr_storage*
>(
message->msg_name),
138 message->msg_namelen, destination)) {
141 translated.msg_name = &destination;
142 translated.msg_namelen = EndpointLength;
144 return UnixSocketSyscalls::sendto_msg(&translated, {});
147 sockaddr_storage source = {};
149 translated.msg_name = &source;
150 translated.msg_namelen =
sizeof(source);
151 const ssize_t result = UnixSocketSyscalls::recvfrom_msg(&translated, rights);
155 message->msg_flags = translated.msg_flags;
157 if (
message->msg_name && getType() == SOCK_DGRAM) {
158 auto decoded = decode(source, translated.msg_namelen);
159 if (!decoded.sin_addr.s_addr) {
160 decoded.sin_addr.s_addr = HOST_TO_BIG32(Loopback);
162 socklen_t length =
message->msg_namelen;
163 copyAddress(decoded,
reinterpret_cast<sockaddr_storage*
>(
message->msg_name), &length);
170 int accept(sockaddr_storage* address, socklen_t* length,
int flags,
172 sockaddr_storage source = {};
173 socklen_t sourceLength =
sizeof(source);
174 const int result = UnixSocketSyscalls::accept(&source, &sourceLength, flags, accepted);
175 if (result >= 0 && length) {
176 copyAddress(decode(source, sourceLength), address, length);
180 int getsockname(sockaddr_storage* address, socklen_t* length)
override {
181 sockaddr_storage source = {};
182 socklen_t sourceLength =
sizeof(source);
183 if (UnixSocketSyscalls::getsockname(&source, &sourceLength)) {
186 auto decoded = decode(source, sourceLength);
187 if (m_Accepted && !decoded.sin_addr.s_addr) {
188 decoded.sin_addr.s_addr = HOST_TO_BIG32(Loopback);
190 copyAddress(decoded, address, length);
193 int getpeername(sockaddr_storage* address, socklen_t* length)
override {
197 syscallError(ENOTCONN);
200 copyAddress(m_Peer, address, length);
203 sockaddr_storage source = {};
204 socklen_t sourceLength =
sizeof(source);
205 if (UnixSocketSyscalls::getpeername(&source, &sourceLength)) {
208 auto decoded = decode(source, sourceLength);
209 if (!decoded.sin_addr.s_addr) {
210 decoded.sin_addr.s_addr = HOST_TO_BIG32(Loopback);
212 copyAddress(decoded, address, length);
215 int setsockopt(
int level,
int option,
const void* value, socklen_t length)
override {
216 if ((level == IPPROTO_TCP && option == TCP_NODELAY && getType() == SOCK_STREAM) ||
217 (level == SOL_SOCKET && option == SO_REUSEADDR)) {
218 if (length <
sizeof(
int)) {
219 syscallError(EINVAL);
223 (level == IPPROTO_TCP ? m_NoDelay : m_ReuseAddress) = *
static_cast<const int*
>(value) != 0;
226 syscallError(ENOPROTOOPT);
229 int getsockopt(
int level,
int option,
void* value, socklen_t* length)
override {
230 if ((level == IPPROTO_TCP && option == TCP_NODELAY) ||
231 (level == SOL_SOCKET && option == SO_REUSEADDR)) {
232 if (*length <
sizeof(
int)) {
233 syscallError(EINVAL);
237 *
static_cast<int*
>(value) = level == IPPROTO_TCP ? m_NoDelay : m_ReuseAddress;
238 *length =
sizeof(int);
241 if (level == SOL_SOCKET && (option == SO_TYPE || option == SO_ERROR)) {
242 return UnixSocketSyscalls::getsockopt(level, option, value, length);
244 syscallError(ENOPROTOOPT);
258 const auto space = m_NetworkNamespace;
261 space->release(token);
267 return new LoopbackSocket(getType(), getProtocol(), m_NetworkNamespace,
true);
271 int bindLocked(uint32_t ip, uint16_t port) {
272 const uint64_t token = m_NetworkNamespace->reserve(getType(), ip, port);
276 sockaddr_storage local;
277 endpoint(local, getType(), ip, port, token);
279 m_NetworkNamespace->release(token);
285 bool ensureBound(uint32_t address) {
291 return m_Accepted || m_Token || bindLocked(address, 0) == 0;
293 bool destinationEndpoint(
const sockaddr_storage* address, socklen_t length,
294 sockaddr_storage& output) {
295 uint32_t ip, boundIp;
298 if (!internetAddress(address, length, ip, port)) {
304 if (!m_NetworkNamespace->find(getType(), ip, port, boundIp, token)) {
307 endpoint(output, getType(), boundIp, port, token);
311 uint64_t m_Token = 0;
312 const bool m_Accepted;
313 bool m_HasPeer =
false, m_NoDelay =
false, m_ReuseAddress =
false, m_Closing =
false;
314 sockaddr_in m_Peer = {};
318NetworkSyscalls* posix_network_socket(
int domain,
int type,
int protocol,
320 if (domain == AF_INET) {
321 auto* socket =
new LoopbackSocket(type, protocol, space);
323 syscallError(ENOMEM);
328 return posix_route_netlink_socket(type, protocol, space);
330 syscallError(EAFNOSUPPORT);
static ProcessorInformation & information()
virtual int listen(int backlog)
virtual void lastDescriptorClosed()
virtual int bind(const struct sockaddr_storage *address, socklen_t addrlen)
virtual bool create()
Implementation-specific final socket creation logic.