2#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 1
3#include "network-namespace.h"
4#include "pedigree/kernel/LockGuard.h"
5#include "pedigree/kernel/syscallError.h"
6#include "pedigree/kernel/utilities/utility.h"
10#include "PosixSubsystem.h"
11#include "net-syscalls.h"
12#include <netinet/in.h>
15uint64_t nextNamespace = 0;
16constexpr uint32_t Loopback = 0x7f000001;
17uint64_t endpointKey(
int type, uint32_t address, uint16_t port) {
18 return (uint64_t(type) << 48) | (uint64_t(address) << 16) | port;
23 : m_Owner(owner), m_Identity(__atomic_add_fetch(&nextNamespace, 1, __ATOMIC_RELAXED)) {}
28 SYSCALL_ERROR(OutOfMemory);
34bool PosixNetworkNamespace::usable()
const {
36 return m_Up && m_Address;
38uint32_t PosixNetworkNamespace::flags()
const {
40 return 8 | (m_Up ? 1 | 0x40 : 0);
42uint32_t PosixNetworkNamespace::address()
const {
46int PosixNetworkNamespace::configureAddress(uint32_t address,
unsigned prefix,
bool exclusive) {
47 if (!posix_namespace_capable(m_Owner, PosixCapabilities::NetAdmin)) {
50 if (address != Loopback || prefix != 8) {
54 if (exclusive && m_Address) {
60int PosixNetworkNamespace::configureLink(uint32_t flags, uint32_t changed) {
61 if (!posix_namespace_capable(m_Owner, PosixCapabilities::NetAdmin)) {
74uint64_t PosixNetworkNamespace::reserve(
int type, uint32_t address, uint16_t& port) {
75 if (port && port < 1024 && !posix_namespace_capable(m_Owner, PosixCapabilities::NetBindService)) {
80 if (address && address != m_Address) {
81 syscallError(EADDRNOTAVAIL);
84 auto available = [&](uint16_t candidate) {
85 for (
auto it = m_Bindings.
begin(); it != m_Bindings.
end(); ++it) {
86 if ((it.key() >> 48) ==
static_cast<unsigned>(type) && uint16_t(it.key()) == candidate) {
87 const uint32_t existing = it.key() >> 16;
88 if (!existing || !address || existing == address) {
96 if (!available(port)) {
97 syscallError(EADDRINUSE);
101 unsigned attempts = 0;
103 if (++attempts > 28232) {
104 syscallError(EADDRINUSE);
108 if (m_NextPort == 61000) {
111 }
while (!available(port));
113 const uint64_t token = ++m_NextToken;
114 if (!m_Bindings.
tryInsert(endpointKey(type, address, port), token)) {
115 syscallError(ENOMEM);
120void PosixNetworkNamespace::release(uint64_t token) {
122 for (
auto it = m_Bindings.
begin(); it != m_Bindings.
end(); ++it) {
123 if (it.value() == token) {
124 m_Bindings.
remove(it.key());
129uint32_t PosixNetworkNamespace::reserveRoutePort(uint32_t preferred,
bool fixed) {
131 if (m_RoutePorts.
lookup(preferred)) {
133 syscallError(EADDRINUSE);
137 preferred = m_NextRoutePort++;
138 }
while (!preferred || m_RoutePorts.
lookup(preferred));
140 if (!m_RoutePorts.
tryInsert(preferred,
true)) {
141 syscallError(ENOMEM);
146void PosixNetworkNamespace::releaseRoutePort(uint32_t port) {
148 m_RoutePorts.
remove(port);
150bool PosixNetworkNamespace::find(
int type, uint32_t address, uint16_t port, uint32_t& boundAddress,
153 if (!m_Up || !m_Address) {
154 syscallError(ENETUNREACH);
157 if (address != m_Address) {
158 syscallError(ENETUNREACH);
161 boundAddress = address;
162 token = m_Bindings.
lookup(endpointKey(type, address, port));
165 token = m_Bindings.
lookup(endpointKey(type, 0, port));
168 syscallError(ECONNREFUSED);
173int posix_network_ioctl(
NetworkSyscalls& socket,
unsigned long request, uintptr_t argument) {
174 const auto& space = socket.networkNamespace();
176 syscallError(ENOTTY);
179 if (request != 0x8910 && request != 0x8913 && request != 0x8914 && request != 0x8915 &&
180 request != 0x8916 && request != 0x891b && request != 0x8921 && request != 0x8933) {
181 syscallError(ENOTTY);
191 char padding[
sizeof(uintptr_t) == 8 ? 24 : 16];
196 syscallError(EFAULT);
199 if (request == 0x8910) {
200 if (snapshot.value.index != 1) {
201 syscallError(ENODEV);
204 ByteSet(snapshot.name, 0,
sizeof(snapshot.name));
205 MemoryCopy(snapshot.name,
"lo", 2);
207 if (snapshot.name[0] !=
'l' || snapshot.name[1] !=
'o' || snapshot.name[2]) {
208 syscallError(ENODEV);
213 snapshot.value.index = 1;
216 snapshot.value.flags = space->flags();
219 snapshot.value.mtu = 65536;
223 sockaddr_in address = {};
224 address.sin_family = AF_INET;
225 address.sin_addr.s_addr = HOST_TO_BIG32(request == 0x8915 ? space->address() : 0xff000000);
226 MemoryCopy(&snapshot.value.address, &address,
sizeof(address));
230 const int error = space->configureLink(snapshot.value.flags, 1);
239 MemoryCopy(&address, &snapshot.value.address,
sizeof(address));
241 address.sin_family != AF_INET
243 : space->configureAddress(BIG_TO_HOST32(address.sin_addr.s_addr), 8,
false);
253 syscallError(EFAULT);
static bool copyFromUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static bool copyToUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static SharedPointer< PosixNetworkNamespace > tryAllocate(Args...)
bool tryInsert(const K &key, const E &value)
void remove(const K &key)
E lookup(const K &key) const