2#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 1
3#include "pedigree/kernel/LockGuard.h"
4#include "pedigree/kernel/process/ConditionVariable.h"
5#include "pedigree/kernel/process/Process.h"
6#include "pedigree/kernel/process/TerminationDeferral.h"
7#include "pedigree/kernel/process/Thread.h"
8#include "pedigree/kernel/processor/Processor.h"
9#include "pedigree/kernel/processor/ProcessorInformation.h"
10#include "pedigree/kernel/syscallError.h"
11#include "pedigree/kernel/utilities/utility.h"
15#include "net-syscalls.h"
16#include "network-namespace.h"
22 uint32_t sequence, pid;
25 uint16_t family, padding;
33static_assert(
sizeof(Header) == 16 &&
sizeof(Reply) == 36,
"Linux netlink ABI");
35 syscallError(EOPNOTSUPP);
38uint32_t currentPid() {
47 m_NetworkNamespace = space;
49 ~RouteSocket()
override {
52 bool create()
override {
53 if ((getType() != SOCK_RAW && getType() != SOCK_DGRAM) || getProtocol()) {
54 syscallError(EPROTONOSUPPORT);
59 int bind(
const sockaddr_storage* address, socklen_t length)
override {
60 if (length <
sizeof(Address) || address->ss_family != 16) {
65 MemoryCopy(&value, address,
sizeof(value));
67 syscallError(EOPNOTSUPP);
80 m_NetworkNamespace->reserveRoutePort(value.pid ? value.pid : currentPid(), value.pid != 0);
88 if (rights ||
message->msg_flags) {
93 if (
message->msg_namelen <
sizeof(destination)) {
97 MemoryCopy(&destination,
message->msg_name,
sizeof(destination));
98 if (destination.family != 16 || destination.pid || destination.groups) {
104 for (
size_t i = 0; i < static_cast<size_t>(
message->msg_iovlen); ++i) {
105 const auto& vector =
message->msg_iov[i];
106 if (vector.iov_len >
sizeof(bytes) - length) {
107 syscallError(EMSGSIZE);
110 MemoryCopy(bytes + length, vector.iov_base, vector.iov_len);
111 length += vector.iov_len;
114 if (length <
sizeof(header)) {
115 syscallError(EINVAL);
118 MemoryCopy(&header, bytes,
sizeof(header));
119 if (header.length <
sizeof(header) || header.length > length || length - header.length > 3 ||
120 !(header.flags & 1)) {
121 syscallError(EINVAL);
131 syscallError(ENOBUFS);
135 m_Pid = m_NetworkNamespace->reserveRoutePort(currentPid(),
false);
141 const int error = request(header, bytes +
sizeof(header), header.length -
sizeof(header));
142 if (error || (header.flags & 4)) {
143 Reply& reply = m_Replies[(m_Head + m_Count) % 16];
144 reply = {{
sizeof(Reply), 2, 0, header.sequence, m_Pid}, -error, header};
146 ++m_Generations.read;
150 m_Changed.broadcast();
159 const int inputFlags =
message->msg_flags;
160 if (inputFlags & ~(MSG_DONTWAIT | MSG_TRUNC | MSG_WAITALL)) {
161 return unsupported();
164 while (!m_Count && !m_Closed) {
165 if (!isBlocking() || (inputFlags & MSG_DONTWAIT)) {
167 syscallError(EAGAIN);
170 ConditionVariable::Error error = ConditionVariable::NoError;
171 if (!m_Changed.wait(m_Lock, error)) {
184 const Reply reply = m_Replies[m_Head];
185 m_Head = (m_Head + 1) % 16;
186 if (m_Count-- == 16) {
187 ++m_Generations.write;
191 for (
size_t i = 0; i < static_cast<size_t>(
message->msg_iovlen) && copied <
sizeof(reply);
193 const auto& vector =
message->msg_iov[i];
194 const size_t amount =
195 vector.iov_len <
sizeof(reply) - copied ? vector.iov_len : sizeof(reply) - copied;
196 MemoryCopy(vector.iov_base,
reinterpret_cast<const uint8_t*
>(&reply) + copied, amount);
200 const Address address = {16, 0, 0, 0};
201 MemoryCopy(
message->msg_name, &address,
202 message->msg_namelen <
sizeof(address) ?
message->msg_namelen : sizeof(address));
203 message->msg_namelen =
sizeof(address);
206 message->msg_flags = copied <
sizeof(reply) ? MSG_TRUNC : 0;
208 return inputFlags & MSG_TRUNC ?
sizeof(reply) : copied;
210 int getsockname(sockaddr_storage* address, socklen_t* length)
override {
212 const Address value = {16, 0, m_Pid, 0};
213 MemoryCopy(address, &value, *length <
sizeof(value) ? *length : sizeof(value));
214 *length =
sizeof(value);
217 int getpeername(sockaddr_storage*, socklen_t*)
override {
218 syscallError(ENOTCONN);
221 int connect(
const sockaddr_storage*, socklen_t)
override {
222 return unsupported();
224 int listen(
int)
override {
225 return unsupported();
227 int accept(sockaddr_storage*, socklen_t*,
int,
DescriptorLease*)
override {
228 return unsupported();
230 int shutdown(
int)
override {
231 return unsupported();
233 int setsockopt(
int,
int,
const void*, socklen_t)
override {
234 syscallError(ENOPROTOOPT);
237 int getsockopt(
int level,
int option,
void* value, socklen_t* length)
override {
238 if (level != SOL_SOCKET || (option != SO_TYPE && option != SO_ERROR) || *length <
sizeof(
int)) {
239 syscallError(ENOPROTOOPT);
242 *
static_cast<int*
>(value) = option == SO_TYPE ? getType() : 0;
243 *length =
sizeof(int);
246 bool canPoll()
const override {
249 ReadyMask
queryReady(
bool reading,
bool writing)
override {
251 return (m_Closed ? ReadyInvalid | ReadyHangup
252 : (reading && m_Count ? ReadyRead : ReadyNone) |
253 (writing && m_Count < 16 ? ReadyWrite : ReadyNone)) |
254 pendingReceiveReadiness();
258 return withReceiveErrorGeneration(m_Generations);
268 m_NetworkNamespace->releaseRoutePort(m_Pid);
271 m_Changed.broadcast();
272 m_ReadinessNotifications.closeAndWait();
277 int request(
const Header& header,
const uint8_t* payload,
size_t length) {
278 if (header.type == 16) {
280 uint8_t family, padding;
283 uint32_t flags, change;
285 if (length !=
sizeof(link)) {
288 MemoryCopy(&link, payload,
sizeof(link));
289 if (link.index != 1) {
292 if (link.family || link.type) {
295 return m_NetworkNamespace->configureLink(link.flags, link.change);
297 if (header.type == 20) {
298 struct InterfaceAddress {
299 uint8_t family, prefix, flags, scope;
302 if (length <
sizeof(address)) {
305 MemoryCopy(&address, payload,
sizeof(address));
306 if (address.index != 1) {
309 if (address.family != AF_INET || address.scope != 254) {
312 if (!(header.flags & 0x400) || (address.flags & ~0x80)) {
315 uint32_t local = 0, peer = 0;
316 size_t offset =
sizeof(address);
317 while (offset < length) {
319 uint16_t length, type;
321 if (length - offset <
sizeof(attribute)) {
324 MemoryCopy(&attribute, payload + offset,
sizeof(attribute));
325 if (attribute.length != 8 || attribute.length > length - offset) {
329 MemoryCopy(&value, payload + offset +
sizeof(attribute),
sizeof(value));
330 if (attribute.type == 1) {
331 peer = BIG_TO_HOST32(value);
332 }
else if (attribute.type == 2) {
333 local = BIG_TO_HOST32(value);
337 offset += (attribute.length + 3) & ~
size_t(3);
339 if (!local || (peer && peer != local)) {
342 return m_NetworkNamespace->configureAddress(local, address.prefix, header.flags & 0x200);
348 Reply m_Replies[16] = {};
349 size_t m_Head = 0, m_Count = 0;
351 bool m_Bound =
false, m_Closed =
false;
358 auto* socket =
new RouteSocket(type, protocol, space);
360 syscallError(ENOMEM);
static bool mutexAcquired(Error error)
bool beginDescriptorClose()
virtual ReadyMask queryReady(bool reading, bool writing)
virtual void lastDescriptorClosed()
ReadinessGenerations readinessGenerations() override
size_t getUserspaceId() const
static ProcessorInformation & information()
void notifyReadiness(ReadyMask mask)
void closeReadiness(ReadyMask mask=ReadyInvalid|ReadyHangup)