2#include "mqueue-netlink.h"
3#include "pedigree/kernel/LockGuard.h"
4#include "pedigree/kernel/process/TerminationDeferral.h"
5#include "pedigree/kernel/syscallError.h"
6#include "pedigree/kernel/utilities/assert.h"
7#include "pedigree/kernel/utilities/utility.h"
13 SYSCALL_ERROR(OperationNotSupported);
18MqueueNetlinkSocket::MqueueNetlinkSocket(
int type,
int protocol)
29MqueueNetlinkSocket::~MqueueNetlinkSocket() {
34 if ((getType() != SOCK_RAW && getType() != SOCK_DGRAM) || getProtocol()) {
35 SYSCALL_ERROR(ProtocolNotAvailable);
41bool MqueueNetlinkSocket::reserveCookie() {
44 SYSCALL_ERROR(BadFileDescriptor);
47 if (m_Count + m_Reserved == 64) {
48 SYSCALL_ERROR(NoMoreBuffers);
55void MqueueNetlinkSocket::deliverCookie(
const uint8_t cookie[32],
bool removed) {
63 uint8_t* target = m_Cookies[(m_Head + m_Count) % 64];
64 MemoryCopy(target, cookie, 32);
65 target[31] = removed ? 2 : 1;
89bool MqueueNetlinkSocket::canPoll()
const {
96 const ReadyMask ready = m_Closed ? ReadyInvalid | ReadyHangup
97 : reading && m_Count ? ReadyRead
99 return ready | pendingReceiveReadiness();
104 return withReceiveErrorGeneration(m_Generations);
107ssize_t MqueueNetlinkSocket::recvfrom_msg(
struct msghdr*
message,
113 const int inputFlags =
message->msg_flags;
114 const int allowedFlags = MSG_DONTWAIT | MSG_NOSIGNAL | MSG_WAITALL | MSG_PEEK | MSG_TRUNC;
115 if (inputFlags & ~allowedFlags) {
116 return unsupported();
119 for (
size_t n = 0; n < static_cast<size_t>(
message->msg_iovlen); ++n) {
120 capacity +=
message->msg_iov[n].iov_len;
126 SYSCALL_ERROR(BadFileDescriptor);
129 if (!isBlocking() || (inputFlags & MSG_DONTWAIT)) {
131 SYSCALL_ERROR(NoMoreProcesses);
134 ConditionVariable::Error error = ConditionVariable::NoError;
135 if (!m_Changed.
wait(m_Lock, error)) {
139 SYSCALL_ERROR(Interrupted);
143 const size_t length = capacity < 32 ? capacity : 32;
145 for (
size_t n = 0; n < static_cast<size_t>(
message->msg_iovlen) && copied < length; ++n) {
146 const auto& vector =
message->msg_iov[n];
147 const size_t amount = vector.iov_len < length - copied ? vector.iov_len : length - copied;
148 MemoryCopy(vector.iov_base, m_Cookies[m_Head] + copied, amount);
151 if (!(inputFlags & MSG_PEEK)) {
152 m_Head = (m_Head + 1) % 64;
156 message->msg_flags = length < 32 ? MSG_TRUNC : 0;
159 return inputFlags & MSG_TRUNC ? 32 :
static_cast<ssize_t
>(length);
162int MqueueNetlinkSocket::connect(
const struct sockaddr_storage*, socklen_t) {
163 return unsupported();
166 return unsupported();
168int MqueueNetlinkSocket::listen(
int) {
169 return unsupported();
171int MqueueNetlinkSocket::bind(
const struct sockaddr_storage*, socklen_t) {
172 return unsupported();
174int MqueueNetlinkSocket::accept(
struct sockaddr_storage*, socklen_t*,
int,
DescriptorLease*) {
175 return unsupported();
177int MqueueNetlinkSocket::shutdown(
int) {
178 return unsupported();
180int MqueueNetlinkSocket::getpeername(
struct sockaddr_storage*, socklen_t*) {
181 SYSCALL_ERROR(NotConnected);
184int MqueueNetlinkSocket::getsockname(
struct sockaddr_storage* address, socklen_t* length) {
185 struct NetlinkAddress {
186 uint16_t family, padding;
187 uint32_t pid, groups;
188 } result = {16, 0, 0, 0};
189 const size_t amount = *length <
sizeof(result) ? *length : sizeof(result);
190 MemoryCopy(address, &result, amount);
191 *length =
sizeof(result);
194int MqueueNetlinkSocket::setsockopt(
int,
int,
const void*, socklen_t) {
195 SYSCALL_ERROR(ProtocolNotAvailable);
198int MqueueNetlinkSocket::getsockopt(
int level,
int option,
void* value, socklen_t* length) {
199 if (level == SOL_SOCKET && (option == SO_TYPE || option == SO_ERROR) && *length >=
sizeof(
int)) {
200 const int result = option == SO_TYPE ? getType() : 0;
201 MemoryCopy(value, &result,
sizeof(result));
202 *length =
sizeof(result);
205 SYSCALL_ERROR(ProtocolNotAvailable);
MUST_USE_RESULT bool wait(Mutex &mutex, Time::Timestamp &timeout, Error &error, WaitQueue::StackDiscardCleanup onStackDiscard=nullptr, void *stackDiscardContext=nullptr)
static bool mutexAcquired(Error error)
void lastDescriptorClosed() override
ReadinessGenerations readinessGenerations() override
ReadyMask queryReady(bool reading, bool writing) override
bool beginDescriptorClose()
OperationBarrier m_ReadinessNotifications
void notifyReadiness(ReadyMask mask)
void closeReadiness(ReadyMask mask=ReadyInvalid|ReadyHangup)
bool acquire(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)