The Pedigree Project 0.1
net-syscalls.h
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#ifndef NET_SYSCALLS_H
21#define NET_SYSCALLS_H
22
23#include "pedigree/kernel/Atomic.h"
24#include "pedigree/kernel/LockGuard.h"
25#include "pedigree/kernel/process/Mutex.h"
26#include "pedigree/kernel/process/OperationBarrier.h"
27#include "pedigree/kernel/process/Readiness.h"
28#include "pedigree/kernel/utilities/List.h"
29#include "pedigree/kernel/utilities/String.h"
30#include "pedigree/kernel/utilities/Tree.h"
31
32#include "logging.h"
33#include "modules/subsys/posix/UnixFilesystem.h"
34#include "network-namespace.h"
35#include <sys/socket.h>
36#include <sys/types.h>
37
38// Must be after sys/types.h to avoid problems with endian.h
40
41extern Filesystem* g_pUnixSocketBacking;
42
43struct sockaddr;
44struct pbuf;
45struct netbuf;
46struct netconn;
47
48class Semaphore;
50class FileDescriptor;
51class DescriptorLease;
52class UnixSocket;
55class Process;
56class Thread;
57class Event;
58
64bool finishInterruptibleSocketCall(Thread* thread, ssize_t result);
65bool finishInterruptibleSocketCall(Thread* thread, bool result) = delete;
66
67#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
68using UnixEndpointMutationLockHook = void (*)();
69using UnixEndpointReadinessLeaseHook = void (*)();
70void setUnixEndpointMutationLockHookForTest(UnixEndpointMutationLockHook hook);
71void setUnixEndpointReadinessLeaseHookForTest(UnixEndpointReadinessLeaseHook hook);
72#endif
73
74ssize_t posix_send_descriptor(const DescriptorLease& descriptor, const void* buffer,
75 size_t bufferLength, int flags, bool kernelBuffer = false);
76ssize_t posix_recv_descriptor(const DescriptorLease& descriptor, void* buffer, size_t bufferLength,
77 int flags);
78ssize_t posix_sendmsg_descriptor(
79 const DescriptorLease& descriptor, const struct msghdr* message,
81 bool kernelBuffer = false);
82ssize_t posix_recvmsg_descriptor(const DescriptorLease& descriptor, struct msghdr* message,
83 SharedPointer<SocketRights>* rights = nullptr);
84
86 public:
87 NetworkSyscalls(int domain, int type, int protocol);
88 virtual ~NetworkSyscalls();
89
93 return nullptr;
94 }
95 virtual bool create();
96 virtual int connect(const struct sockaddr_storage* address, socklen_t addrlen) = 0;
97
98 virtual ssize_t sendto_msg(const struct msghdr* msghdr,
99 const SharedPointer<SocketRights>& rights) = 0;
100 virtual ssize_t recvfrom_msg(struct msghdr* msghdr, SharedPointer<SocketRights>* rights) = 0;
101
102 virtual ssize_t sendto(const void* buffer, size_t bufferlen, int flags,
103 const struct sockaddr_storage* address, socklen_t addrlen);
104 virtual ssize_t recvfrom(void* buffer, size_t bufferlen, int flags,
105 struct sockaddr_storage* address, socklen_t* addrlen);
106
107 virtual int listen(int backlog) = 0;
108 virtual int bind(const struct sockaddr_storage* address, socklen_t addrlen) = 0;
109 virtual int accept(struct sockaddr_storage* address, socklen_t* addrlen, int flags,
110 DescriptorLease* accepted = nullptr) = 0;
111
112 virtual int shutdown(int how);
113
114 virtual int getpeername(struct sockaddr_storage* address, socklen_t* address_len) = 0;
115 virtual int getsockname(struct sockaddr_storage* address, socklen_t* address_len) = 0;
116
117 virtual int setsockopt(int level, int optname, const void* optvalue, socklen_t optlen) = 0;
118 virtual int getsockopt(int level, int optname, void* optvalue, socklen_t* optlen) = 0;
119
120 virtual bool canPoll() const;
121 virtual bool poll(bool& read, bool& write, bool& error, Semaphore* waiter);
122 virtual void unPoll(Semaphore* waiter);
123
125 virtual ReadyMask queryReady(bool reading, bool writing);
127
130 void removeDescriptorOwner();
131
134
141 virtual void lastDescriptorClosed();
142
143 virtual bool monitor(Thread* pThread, Event* pEvent);
144 virtual bool unmonitor(Event* pEvent);
145
146 void associate(FileDescriptor* fd);
147
148 int getDomain() const {
149 return m_Domain;
150 }
151
152 int getType() const {
153 return m_Type;
154 }
155
156 int getProtocol() const {
157 return m_Protocol;
158 }
159
160 const NetworkNamespaceRef& networkNamespace() const {
161 return m_NetworkNamespace;
162 }
163
164 bool isBlocking() const;
165
166 virtual void setBlocking(bool blocking);
167
168 int takeReceiveError();
169 void deferReceiveError(int error);
170
171 protected:
172 virtual bool usesLocalEndpointLifetime() const {
173 return false;
174 }
175 ReadyMask pendingReceiveReadiness() const;
176 ReadinessGenerations withReceiveErrorGeneration(ReadinessGenerations generations) const;
177
180
181 bool hasLastDescriptorClosed() const;
182
183 SharedPointer<NetworkSyscalls> acquireDescriptorLifetime() const;
184 SharedPointer<NetworkSyscalls> releaseDescriptorLifetime();
185
186 int m_Domain;
187 int m_Type;
188 int m_Protocol;
189 NetworkNamespaceRef m_NetworkNamespace;
190
191 Atomic<bool> m_Blocking;
192 mutable Mutex m_ReceiveErrorLock;
193 int m_ReceiveError = 0;
194 uint64_t m_ReceiveErrorGeneration = 0;
195
198
199 private:
200 mutable Mutex m_LifecycleLock;
201 size_t m_DescriptorOwners;
202 bool m_DescriptorAdmissionOpen;
203 bool m_LastDescriptorClosed;
204 SharedPointer<NetworkSyscalls> m_DescriptorLifetime;
205};
206
208 public:
209 LwipSocketSyscalls(int domain, int type, int protocol);
210 virtual ~LwipSocketSyscalls();
211
213 virtual bool create();
214 virtual int connect(const struct sockaddr_storage* address, socklen_t addrlen);
215
216 virtual ssize_t sendto_msg(const struct msghdr* msghdr,
217 const SharedPointer<SocketRights>& rights);
218 virtual ssize_t recvfrom_msg(struct msghdr* msghdr, SharedPointer<SocketRights>* rights);
219
220 virtual int listen(int backlog);
221 virtual int bind(const struct sockaddr_storage* address, socklen_t addrlen);
222 virtual int accept(struct sockaddr_storage* address, socklen_t* addrlen, int flags,
223 DescriptorLease* accepted = nullptr);
224
225 virtual int shutdown(int how);
226
227 virtual int getpeername(struct sockaddr_storage* address, socklen_t* address_len);
228 virtual int getsockname(struct sockaddr_storage* address, socklen_t* address_len);
229
230 virtual int setsockopt(int level, int optname, const void* optvalue, socklen_t optlen);
231 virtual int getsockopt(int level, int optname, void* optvalue, socklen_t* optlen);
232
233 virtual bool canPoll() const;
234 virtual bool poll(bool& read, bool& write, bool& error, Semaphore* waiter);
235 virtual void unPoll(Semaphore* waiter);
236 virtual ReadyMask queryReady(bool reading, bool writing);
238 virtual void lastDescriptorClosed();
239
240 virtual void setBlocking(bool blocking);
241
242 private:
243 static Tree<struct netconn*, LwipSocketSyscalls*> m_SyscallObjects;
244 static Mutex m_SyscallObjectsLock;
245
246 static void netconnCallback(struct netconn* conn, enum netconn_evt evt, uint16_t len);
247 static void lwipToSyscallError(err_t err);
248 void registerSocket();
249 ReadyMask readinessLevelLocked() const;
250 void recordReadinessRisesLocked(ReadyMask previous);
251
252 struct netconn* m_Socket;
253 Mutex m_ReceiveLock;
254
256 LwipMetadata();
257
258 ssize_t recv;
259 ssize_t send;
260 err_t error;
261 bool closed;
262 bool peerClosed;
263 bool writeClosed;
264 bool listening;
265 bool partialRead;
266 bool receivingQueuedData;
267
268 Mutex lock;
269 List<Semaphore*> semaphores;
270
271 size_t offset;
272 struct pbuf* pb;
273 struct netbuf* buf;
274 ReadinessGenerations generations;
275 } m_Metadata;
276};
277
279 public:
280 UnixSocketSyscalls(int domain, int type, int protocol);
281 virtual ~UnixSocketSyscalls();
282
284 virtual bool create();
285 virtual int connect(const struct sockaddr_storage* address, socklen_t addrlen);
286
287 virtual ssize_t sendto_msg(const struct msghdr* msghdr,
288 const SharedPointer<SocketRights>& rights);
289 virtual ssize_t recvfrom_msg(struct msghdr* msghdr, SharedPointer<SocketRights>* rights);
290
291 virtual int listen(int backlog);
292 virtual int bind(const struct sockaddr_storage* address, socklen_t addrlen);
293 virtual int accept(struct sockaddr_storage* address, socklen_t* addrlen, int flags,
294 DescriptorLease* accepted = nullptr);
295
296 virtual int shutdown(int how);
297
298 virtual int getpeername(struct sockaddr_storage* address, socklen_t* address_len);
299 virtual int getsockname(struct sockaddr_storage* address, socklen_t* address_len);
300
301 virtual int setsockopt(int level, int optname, const void* optvalue, socklen_t optlen);
302 virtual int getsockopt(int level, int optname, void* optvalue, socklen_t* optlen);
303
304 virtual bool canPoll() const;
305 virtual bool poll(bool& read, bool& write, bool& error, Semaphore* waiter);
306 virtual void unPoll(Semaphore* waiter);
307 virtual ReadyMask queryReady(bool reading, bool writing);
309 virtual void lastDescriptorClosed();
310
311 virtual bool monitor(Thread* pThread, Event* pEvent);
312 virtual bool unmonitor(Event* pEvent);
313
316 bool pairWith(UnixSocketSyscalls* other);
317
318 protected:
319 bool usesLocalEndpointLifetime() const override {
320 return true;
321 }
322 virtual UnixSocketSyscalls* createAcceptedSocket();
323
324 private:
325 friend class UnixSocketGeneration;
326 friend bool runHostedUnixEndpointLifetimeRegression(Process* process);
327
328 // Endpoint generations and their ownership must not be duplicated implicitly.
329 NOT_COPYABLE_OR_ASSIGNABLE(UnixSocketSyscalls);
330
331 static Tree<UnixSocket*, UnixSocketSyscalls*> m_SyscallObjects;
332 static Tree<UnixSocket*, UnixSocket*> m_Peers;
333 static Tree<UnixSocket*, UnixSocket*> m_PendingListeners;
334 static Mutex m_SyscallObjectsLock;
336 public:
339
340 private:
341 UnixSocketSyscalls& m_Socket;
342 LockGuard<Mutex> m_Guard;
343 };
344
346 public:
349
350 private:
351 UnixSocketSyscalls& m_First;
352 UnixSocketSyscalls& m_Second;
353 LockGuard<Mutex> m_FirstGuard;
354 LockGuard<Mutex> m_SecondGuard;
355 };
356
358 public:
362
363 MUST_USE_RESULT bool acquire(UnixSocketSyscalls& socket);
364
365 explicit operator bool() const {
366 return m_Acquired;
367 }
368
369 private:
370 UnixSocketSyscalls* m_Socket;
373 bool m_Acquired;
374 };
375
376 void registerSocket(UnixSocket* socket);
377 void registerPeer(UnixSocket* socket, UnixSocket* peer, UnixSocket* listener = nullptr);
378 void unregisterPeer(UnixSocket* socket, UnixSocket* peer);
379 static void unregisterSocket(UnixSocket* socket, List<UnixSocket*>& peers);
380 void notifyPeer(UnixSocket* socket, ReadyMask mask);
381 static void notifySocket(UnixSocket* socket, ReadyMask mask);
382 String abstractKey(const String& address) const;
383 bool publishAbstractSocket(const String& address,
384 const SharedPointer<UnixSocketReference>& reference);
385 SharedPointer<UnixSocketReference> acquireSocket(const String& address);
386 void removeAbstractSocket(const String& address, UnixSocket* socket);
387
388 SharedPointer<UnixSocketGeneration> acquireLocalEndpoint() const;
389 void replaceLocalEndpoint(UnixSocket* socket, bool tracked, const String* localPath = nullptr);
390 void replaceLocalEndpoint(const SharedPointer<UnixSocketReference>& reference,
391 const String* localPath, bool ownsAbstractName);
392 void tryCompleteEndpointClose();
393
394 UnixSocket::SocketType getSocketType() const;
395
400 Atomic<bool> m_EndpointMutationReleaseInProgress;
401 Atomic<bool> m_EndpointClosePending;
402 Atomic<bool> m_EndpointRetired;
403 Atomic<bool> m_EndpointCloseFinalized;
405 SharedPointer<UnixSocketReference> m_RemoteEndpoint;
406 SharedPointer<UnixSocketGeneration> m_ClosingLocalEndpoint;
407 SharedPointer<UnixSocketReference> m_ClosingRemoteEndpoint;
408
409 String m_LocalPath;
410 String m_RemotePath;
411 bool m_OwnsAbstractName;
412};
413
415struct netconnMetadata* getNetconnMetadata(struct netconn* conn);
416
417int posix_socket(int domain, int type, int protocol);
418int posix_socketpair(int domain, int type, int protocol, int sv[2]);
419int posix_connect(int sock, const struct sockaddr_storage* address, socklen_t addrlen);
420
421ssize_t posix_send(int sock, const void* buff, size_t bufflen, int flags);
422ssize_t posix_sendto(int sock, const void* buff, size_t bufflen, int flags,
423 struct sockaddr_storage* address, socklen_t addrlen);
424ssize_t posix_recv(int sock, void* buff, size_t bufflen, int flags);
425ssize_t posix_recvfrom(int sock, void* buff, size_t bufflen, int flags,
426 struct sockaddr_storage* address, socklen_t* addrlen);
427
428int posix_listen(int sock, int backlog);
429int posix_bind(int sock, const struct sockaddr_storage* address, socklen_t addrlen);
430int posix_accept(int sock, struct sockaddr_storage* address, socklen_t* addrlen);
431int posix_accept4(int sock, struct sockaddr_storage* address, socklen_t* addrlen, int flags);
432
433int posix_shutdown(int socket, int how);
434
435int posix_getpeername(int socket, struct sockaddr_storage* address, socklen_t* address_len);
436int posix_getsockname(int socket, struct sockaddr_storage* address, socklen_t* address_len);
437
438int posix_setsockopt(int sock, int level, int optname, const void* optvalue, socklen_t optlen);
439int posix_getsockopt(int sock, int level, int optname, void* optvalue, socklen_t* optlen);
440
441int posix_sethostname(const char* name, size_t len);
442
443ssize_t posix_sendmsg(int sockfd, const struct msghdr* msg, int flags);
444ssize_t posix_recvmsg(int sockfd, struct msghdr* msg, int flags);
445
446#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
447bool runHostedUnixEndpointLifetimeRegression(Process* process);
448#endif
449
450#endif
Definition Event.h:49
Definition List.h:61
static void netconnCallback(struct netconn *conn, enum netconn_evt evt, uint16_t len)
ReadinessGenerations readinessGenerations() override
virtual int connect(const struct sockaddr_storage *address, socklen_t addrlen)
virtual void lastDescriptorClosed()
virtual int getpeername(struct sockaddr_storage *address, socklen_t *address_len)
virtual int accept(struct sockaddr_storage *address, socklen_t *addrlen, int flags, DescriptorLease *accepted=nullptr)
virtual ReadyMask queryReady(bool reading, bool writing)
virtual bool poll(bool &read, bool &write, bool &error, Semaphore *waiter)
virtual bool create()
Implementation-specific final socket creation logic.
virtual int getsockname(struct sockaddr_storage *address, socklen_t *address_len)
Definition Mutex.h:56
bool beginDescriptorClose()
virtual MqueueNetlinkSocket * asMqueueNetlink()
virtual ReadyMask queryReady(bool reading, bool writing)
MUST_USE_RESULT bool addDescriptorOwner()
virtual void lastDescriptorClosed()
OperationBarrier m_ReadinessNotifications
ReadinessGenerations readinessGenerations() override
void retainDescriptorLifetime(const SharedPointer< NetworkSyscalls > &lifetime)
A key/value dictionary.
Definition Tree.h:33
virtual int listen(int backlog)
virtual void lastDescriptorClosed()
ReadinessGenerations readinessGenerations() override
bool pairWith(UnixSocketSyscalls *other)
virtual int bind(const struct sockaddr_storage *address, socklen_t addrlen)
virtual bool create()
Implementation-specific final socket creation logic.
virtual ReadyMask queryReady(bool reading, bool writing)
s8_t err_t
Definition err.h:76
Definition pbuf.h:161