mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +02:00
850 lines
20 KiB
C
850 lines
20 KiB
C
// Copyright 2017 plutoo
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
|
|
// Complete definition of struct timeout:
|
|
#include <sys/time.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
// For ioctls:
|
|
#include <sys/ioctl.h>
|
|
#include <net/if.h>
|
|
#include <net/if_media.h>
|
|
|
|
#include "types.h"
|
|
#include "result.h"
|
|
#include "kernel/ipc.h"
|
|
#include "kernel/shmem.h"
|
|
#include "kernel/rwlock.h"
|
|
#include "services/bsd.h"
|
|
#include "services/sm.h"
|
|
|
|
__thread Result g_bsdResult;
|
|
__thread int g_bsdErrno;
|
|
|
|
static Service g_bsdSrv;
|
|
static size_t g_bsdSrvIpcBufferSize;
|
|
static Service g_bsdMonitor;
|
|
static u64 g_bsdClientPid = -1;
|
|
|
|
static TransferMemory g_bsdTmem;
|
|
|
|
static const BsdInitConfig g_defaultBsdInitConfig = {
|
|
.version = 1,
|
|
|
|
.tcp_tx_buf_size = 0x8000,
|
|
.tcp_rx_buf_size = 0x10000,
|
|
.tcp_tx_buf_max_size = 0x40000,
|
|
.tcp_rx_buf_max_size = 0x40000,
|
|
|
|
.udp_tx_buf_size = 0x2400,
|
|
.udp_rx_buf_size = 0xA500,
|
|
|
|
.sb_efficiency = 4,
|
|
};
|
|
|
|
/*
|
|
This function computes the minimal size of the transfer memory to be passed to @ref bsdInitalize.
|
|
Should the transfer memory be smaller than that, the BSD sockets service would only send
|
|
ZeroWindow packets (for TCP), resulting in a transfer rate not exceeding 1 byte/s.
|
|
*/
|
|
static size_t _bsdGetTransferMemSizeForConfig(const BsdInitConfig *config) {
|
|
u32 tcp_tx_buf_max_size = config->tcp_tx_buf_max_size != 0 ? config->tcp_tx_buf_max_size : config->tcp_tx_buf_size;
|
|
u32 tcp_rx_buf_max_size = config->tcp_rx_buf_max_size != 0 ? config->tcp_rx_buf_max_size : config->tcp_rx_buf_size;
|
|
u32 sum = tcp_tx_buf_max_size + tcp_rx_buf_max_size + config->udp_tx_buf_size + config->udp_rx_buf_size;
|
|
|
|
sum = ((sum + 0xFFF) >> 12) << 12; // page round-up
|
|
return (size_t)(config->sb_efficiency * sum);
|
|
}
|
|
|
|
static Result _bsdRegisterClient(Service* srv, TransferMemory* tmem, const BsdInitConfig *config, u64* pid_out) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
ipcSendPid(&c);
|
|
ipcSendHandleCopy(&c, tmem->handle);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
BsdInitConfig config;
|
|
u64 pid_reserved;
|
|
u64 tmem_sz;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 0;
|
|
raw->config = *config;
|
|
raw->pid_reserved = 0;
|
|
raw->tmem_sz = tmem->size;
|
|
|
|
Result rc = serviceIpcDispatch(srv);
|
|
|
|
if (R_SUCCEEDED(rc)) {
|
|
IpcParsedCommand r;
|
|
ipcParse(&r);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 result;
|
|
u64 pid;
|
|
} *resp = r.Raw;
|
|
|
|
*pid_out = resp->pid;
|
|
g_bsdResult = rc = resp->result;
|
|
g_bsdErrno = 0;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static Result _bsdStartMonitor(Service* srv, u64 pid) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
ipcSendPid(&c);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
u64 pid;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 1;
|
|
raw->pid = pid;
|
|
|
|
Result rc = serviceIpcDispatch(srv);
|
|
|
|
if (R_SUCCEEDED(rc)) {
|
|
IpcParsedCommand r;
|
|
ipcParse(&r);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 result;
|
|
} *resp = r.Raw;
|
|
|
|
g_bsdResult = rc = resp->result;
|
|
g_bsdErrno = 0;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
typedef struct {
|
|
u64 magic;
|
|
u64 result;
|
|
int ret;
|
|
int errno_;
|
|
} BsdIpcResponseBase;
|
|
|
|
static int _bsdDispatchBasicCommand(IpcCommand *c, IpcParsedCommand *rOut) {
|
|
Result rc = serviceIpcDispatch(&g_bsdSrv);
|
|
IpcParsedCommand r;
|
|
int ret = -1;
|
|
|
|
if (R_SUCCEEDED(rc)) {
|
|
ipcParse(&r);
|
|
|
|
BsdIpcResponseBase *resp = r.Raw;
|
|
|
|
rc = resp->result;
|
|
|
|
if (R_SUCCEEDED(rc)) {
|
|
ret = resp->ret;
|
|
g_bsdErrno = (ret < 0) ? resp->errno_ : 0;
|
|
}
|
|
}
|
|
|
|
if (R_FAILED(rc))
|
|
g_bsdErrno = -1;
|
|
|
|
if(rOut != NULL)
|
|
*rOut = r;
|
|
|
|
g_bsdResult = rc;
|
|
return ret;
|
|
}
|
|
|
|
static int _bsdDispatchCommandWithOutAddrlen(IpcCommand *c, socklen_t *addrlen) {
|
|
IpcParsedCommand r;
|
|
int ret = _bsdDispatchBasicCommand(c, &r);
|
|
if(ret != -1 && addrlen != NULL) {
|
|
struct {
|
|
BsdIpcResponseBase bsd_resp;
|
|
socklen_t addrlen;
|
|
} *resp = r.Raw;
|
|
*addrlen = resp->addrlen;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static int _bsdNameGetterCommand(u32 cmd_id, int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
socklen_t maxaddrlen = addrlen == NULL ? 0 : *addrlen;
|
|
|
|
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, addr, maxaddrlen, 0);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int sockfd;
|
|
} PACKED *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = cmd_id;
|
|
raw->sockfd = sockfd;
|
|
|
|
return _bsdDispatchCommandWithOutAddrlen(&c, addrlen);
|
|
}
|
|
|
|
static int _bsdSocketCreationCommand(u32 cmd_id, int domain, int type, int protocol) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int domain;
|
|
int type;
|
|
int protocol;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = cmd_id;
|
|
raw->domain = domain;
|
|
raw->type = type;
|
|
raw->protocol = protocol;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
const BsdInitConfig *bsdGetDefaultInitConfig(void) {
|
|
return &g_defaultBsdInitConfig;
|
|
}
|
|
|
|
Result bsdInitialize(const BsdInitConfig *config) {
|
|
const char* bsd_srv = "bsd:s";
|
|
|
|
if(serviceIsActive(&g_bsdSrv) || serviceIsActive(&g_bsdMonitor))
|
|
return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized);
|
|
|
|
Result rc = smGetService(&g_bsdSrv, bsd_srv);
|
|
|
|
if (R_FAILED(rc)) {
|
|
bsd_srv = "bsd:u";
|
|
rc = smGetService(&g_bsdSrv, bsd_srv);
|
|
}
|
|
if(R_FAILED(rc)) goto error;
|
|
|
|
rc = ipcQueryPointerBufferSize(g_bsdSrv.handle, &g_bsdSrvIpcBufferSize);
|
|
if(R_FAILED(rc)) goto error;
|
|
|
|
rc = smGetService(&g_bsdMonitor, bsd_srv);
|
|
if(R_FAILED(rc)) goto error;
|
|
|
|
rc = tmemCreate(&g_bsdTmem, _bsdGetTransferMemSizeForConfig(config), 0);
|
|
if(R_FAILED(rc)) goto error;
|
|
|
|
rc = _bsdRegisterClient(&g_bsdSrv, &g_bsdTmem, config, &g_bsdClientPid);
|
|
if(R_FAILED(rc)) goto error;
|
|
|
|
rc = _bsdStartMonitor(&g_bsdMonitor, g_bsdClientPid);
|
|
if(R_FAILED(rc)) goto error;
|
|
|
|
return rc;
|
|
|
|
error:
|
|
bsdExit();
|
|
return rc;
|
|
}
|
|
|
|
void bsdExit(void) {
|
|
g_bsdSrvIpcBufferSize = 0;
|
|
g_bsdClientPid = 0;
|
|
serviceClose(&g_bsdMonitor);
|
|
serviceClose(&g_bsdSrv);
|
|
tmemClose(&g_bsdTmem);
|
|
}
|
|
|
|
int bsdSocket(int domain, int type, int protocol) {
|
|
return _bsdSocketCreationCommand(2, domain, type, protocol);
|
|
}
|
|
|
|
int bsdSocketExempt(int domain, int type, int protocol) {
|
|
return _bsdSocketCreationCommand(3, domain, type, protocol);
|
|
}
|
|
|
|
int bsdOpen(const char *pathname, int flags) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
size_t pathlen = strlen(pathname) + 1;
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, pathname, pathlen, 0);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int flags;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 4;
|
|
raw->flags = flags;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
int bsdSelect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, readfds, readfds == NULL ? 0 : sizeof(fd_set), 0);
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, writefds, writefds == NULL ? 0 : sizeof(fd_set), 1);
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 2);
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 3);
|
|
|
|
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, readfds, readfds == NULL ? 0 : sizeof(fd_set), 0);
|
|
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, writefds, writefds == NULL ? 0 : sizeof(fd_set), 1);
|
|
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 2);
|
|
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 3);
|
|
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int nfds;
|
|
struct timeval timeout;
|
|
bool nullTimeout;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 5;
|
|
raw->nfds = nfds;
|
|
if(!(raw->nullTimeout = timeout == NULL))
|
|
raw->timeout = *timeout;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
int bsdPoll(struct pollfd *fds, nfds_t nfds, int timeout) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, fds, nfds * sizeof(struct pollfd), 0);
|
|
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, fds, nfds * sizeof(struct pollfd), 0);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
nfds_t nfds;
|
|
int timeout;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 6;
|
|
raw->nfds = nfds;
|
|
raw->timeout = timeout;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
int bsdSysctl(const int *name, unsigned int namelen, void *oldp, size_t *oldlenp, const void *newp, size_t newlen) {
|
|
IpcCommand c;
|
|
size_t inlen = oldlenp == NULL ? 0 : *oldlenp;
|
|
|
|
ipcInitialize(&c);
|
|
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, name, 4 * namelen, 0);
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, newp, newlen, 1);
|
|
|
|
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, oldp, inlen, 0);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 7;
|
|
|
|
IpcParsedCommand r;
|
|
int ret = _bsdDispatchBasicCommand(&c, &r);
|
|
if(ret != -1 && oldlenp != NULL) {
|
|
struct {
|
|
BsdIpcResponseBase bsd_resp;
|
|
size_t oldlenp;
|
|
} *resp = r.Raw;
|
|
*oldlenp = resp->oldlenp;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
ssize_t bsdRecv(int sockfd, void *buf, size_t len, int flags) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, buf, len, 0);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int sockfd;
|
|
int flags;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 8;
|
|
raw->sockfd = sockfd;
|
|
raw->flags = flags;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
ssize_t bsdRecvFrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen){
|
|
IpcCommand c;
|
|
socklen_t inaddrlen = addrlen == NULL ? 0 : *addrlen;
|
|
|
|
ipcInitialize(&c);
|
|
|
|
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, buf, len, 0);
|
|
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, src_addr, inaddrlen, 1);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int sockfd;
|
|
int flags;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 9;
|
|
raw->sockfd = sockfd;
|
|
raw->flags = flags;
|
|
|
|
return _bsdDispatchCommandWithOutAddrlen(&c, addrlen);
|
|
}
|
|
|
|
ssize_t bsdSend(int sockfd, const void* buf, size_t len, int flags) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, buf, len, 0);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int sockfd;
|
|
int flags;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 10;
|
|
raw->sockfd = sockfd;
|
|
raw->flags = flags;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
ssize_t bsdSendTo(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, buf, len, 0);
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, dest_addr, addrlen, 1);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int sockfd;
|
|
int flags;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 11;
|
|
raw->sockfd = sockfd;
|
|
raw->flags = flags;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
int bsdAccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
|
|
return _bsdNameGetterCommand(12, sockfd, addr, addrlen);
|
|
}
|
|
|
|
int bsdBind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, addr, addrlen, 0);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int sockfd;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 13;
|
|
raw->sockfd = sockfd;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
int bsdConnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, addr, addrlen, 0);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int sockfd;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 14;
|
|
raw->sockfd = sockfd;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
int bsdGetPeerName(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
|
|
return _bsdNameGetterCommand(15, sockfd, addr, addrlen);
|
|
}
|
|
|
|
int bsdGetSockName(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
|
|
return _bsdNameGetterCommand(16, sockfd, addr, addrlen);
|
|
}
|
|
|
|
int bsdGetSockOpt(int sockfd, int level, int optname, void *optval, socklen_t *optlen) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
socklen_t inoptlen = optlen == NULL ? 0 : *optlen;
|
|
|
|
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, optval, inoptlen, 0);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int sockfd;
|
|
int level;
|
|
int optname;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 17;
|
|
raw->sockfd = sockfd;
|
|
raw->level = level;
|
|
raw->optname = optname;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
int bsdListen(int sockfd, int backlog) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int sockfd;
|
|
int backlog;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 18;
|
|
raw->sockfd = sockfd;
|
|
raw->backlog = backlog;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
int bsdIoctl(int fd, int request, void *data) {
|
|
IpcCommand c;
|
|
|
|
const void *in1 = NULL, *in2 = NULL, *in3 = NULL, *in4 = NULL;
|
|
size_t in1sz = 0, in2sz = 0, in3sz = 0, in4sz = 0;
|
|
|
|
void *out1 = NULL, *out2 = NULL, *out3 = NULL, *out4 = NULL;
|
|
size_t out1sz = 0, out2sz = 0, out3sz = 0, out4sz = 0;
|
|
|
|
int bufcount = 1;
|
|
|
|
switch(request) {
|
|
case SIOCGIFCONF: {
|
|
struct ifconf *data_ = (struct ifconf *)data;
|
|
in1 = out1 = data;
|
|
in1sz = out1sz = sizeof(struct ifconf);
|
|
in2 = out2 = data_->ifc_req;
|
|
in2sz = out2sz = data_->ifc_len;
|
|
bufcount = 2;
|
|
break;
|
|
}
|
|
case SIOCGIFMEDIA:
|
|
case SIOCGIFXMEDIA: {
|
|
struct ifmediareq *data_ = (struct ifmediareq *)data;
|
|
in1 = out1 = data;
|
|
in1sz = out1sz = sizeof(struct ifmediareq);
|
|
in2 = out2 = data_->ifm_ulist;
|
|
in2sz = out2sz = 8 * data_->ifm_count;
|
|
bufcount = 2;
|
|
break;
|
|
}
|
|
// Generic ioctl
|
|
default: {
|
|
void *data_ = NULL;
|
|
if(request & IOC_INOUT)
|
|
data_ = data;
|
|
if(request & IOC_IN) {
|
|
in1 = data_;
|
|
in1sz = IOCPARM_LEN(request);
|
|
}
|
|
if(request & IOC_OUT) {
|
|
out1 = data_;
|
|
out1sz = IOCPARM_LEN(request);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
ipcInitialize(&c);
|
|
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, in1, in1sz, 0);
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, in2, in2sz, 1);
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, in3, in3sz, 2);
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, in4, in4sz, 3);
|
|
|
|
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, out1, out1sz, 0);
|
|
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, out2, out2sz, 1);
|
|
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, out3, out3sz, 2);
|
|
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, out4, out4sz, 3);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int fd;
|
|
int request;
|
|
int bufcount;
|
|
} PACKED *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 19;
|
|
raw->fd = fd;
|
|
raw->request = request;
|
|
raw->bufcount = bufcount;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
int bsdFcntl(int fd, int cmd, int flags) {
|
|
IpcCommand c;
|
|
|
|
if(cmd != F_GETFL && cmd != F_SETFL) {
|
|
g_bsdResult = 0;
|
|
g_bsdErrno = EOPNOTSUPP;
|
|
return -1;
|
|
}
|
|
|
|
if(cmd == F_GETFL)
|
|
flags = 0;
|
|
|
|
ipcInitialize(&c);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int fd;
|
|
int cmd;
|
|
int flags;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 20;
|
|
raw->fd = fd;
|
|
raw->cmd = cmd;
|
|
raw->flags = flags;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
int bsdSetSockOpt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, optval, optlen, 0);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int sockfd;
|
|
int level;
|
|
int optname;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 21;
|
|
raw->sockfd = sockfd;
|
|
raw->level = level;
|
|
raw->optname = optname;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
int bsdShutdown(int sockfd, int how) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int sockfd;
|
|
int how;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 22;
|
|
raw->sockfd = sockfd;
|
|
raw->how = how;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
int bsdShutdownAllSockets(int how) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int how;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 23;
|
|
raw->how = how;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
ssize_t bsdWrite(int fd, const void *buf, size_t count) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, buf, count, 0);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int fd;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 24;
|
|
raw->fd = fd;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
ssize_t bsdRead(int fd, void *buf, size_t count) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, buf, count, 0);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int fd;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 25;
|
|
raw->fd = fd;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
int bsdClose(int fd) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int fd;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 26;
|
|
raw->fd = fd;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|
|
|
|
int bsdDuplicateSocket(int sockfd) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int sockfd;
|
|
u64 reserved;
|
|
} *raw;
|
|
|
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 27;
|
|
raw->sockfd = sockfd;
|
|
raw->reserved = 0;
|
|
|
|
return _bsdDispatchBasicCommand(&c, NULL);
|
|
}
|