mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
268 lines
6.7 KiB
C
268 lines
6.7 KiB
C
#include "types.h"
|
|
#include "result.h"
|
|
#include "ipc.h"
|
|
#include "services/sm.h"
|
|
#include "services/sfdnsres.h"
|
|
|
|
#include <string.h>
|
|
|
|
static Result _sfdnsresDispatchCommand(IpcParsedCommand *r, IpcCommand *c, const void *raw, size_t raw_size) {
|
|
Service sfdnsres;
|
|
|
|
Result rc = smGetService(&sfdnsres, "sfdnsres");
|
|
if(R_FAILED(rc)) goto cleanup;
|
|
|
|
memcpy(ipcPrepareHeader(c, raw_size), raw, raw_size);
|
|
|
|
rc = serviceIpcDispatch(&sfdnsres);
|
|
if(R_FAILED(rc)) goto cleanup;
|
|
|
|
ipcParse(r);
|
|
|
|
cleanup:
|
|
serviceClose(&sfdnsres);
|
|
return rc;
|
|
}
|
|
|
|
static Result _sfdnsresDispatchDnsRequest(IpcCommand *c, SfdnsresRequestResults *ret, const void *raw, size_t raw_size, bool has_serialized_data_out) {
|
|
Result rc;
|
|
IpcParsedCommand r;
|
|
ipcSendPid(c);
|
|
|
|
rc = _sfdnsresDispatchCommand(&r, c, &raw, sizeof(raw));
|
|
if(R_FAILED(rc)) return rc;
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 result;
|
|
int ret;
|
|
int errno_;
|
|
int out_serialized_size; // OOB if !has_serialized_data
|
|
} *resp = r.Raw;
|
|
|
|
rc = resp->result;
|
|
if(R_FAILED(rc)) return rc;
|
|
|
|
ret->ret = resp->ret;
|
|
ret->errno_ = resp->errno_;
|
|
ret->out_serialized_size = has_serialized_data_out ? resp->out_serialized_size : 0;
|
|
|
|
return rc;
|
|
}
|
|
|
|
static Result _sfdnsresDnsRequestCommand(IpcCommand *c, u64 cmd_id, SfdnsresRequestResults *ret, const SfdnsresConfig *config, bool has_serialized_data_out, int *arg) {
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int arg;
|
|
int timeout;
|
|
u64 pid_placeholder;
|
|
} raw;
|
|
|
|
raw.magic = SFCI_MAGIC;
|
|
raw.cmd_id = cmd_id;
|
|
raw.arg = arg == NULL ? (config->bypass_nsd ? 0 : 1) : *arg;
|
|
raw.timeout = config->timeout;
|
|
raw.pid_placeholder = 0;
|
|
|
|
return _sfdnsresDispatchDnsRequest(c, ret, &raw, sizeof(raw), has_serialized_data_out);
|
|
}
|
|
|
|
static Result _sfdnsresErrorStringGetterCommand(u64 cmd_id, int err, char *str, size_t str_size) {
|
|
IpcCommand c;
|
|
Result rc;
|
|
IpcParsedCommand r;
|
|
|
|
ipcInitialize(&c);
|
|
ipcAddRecvBuffer(&c, str, str_size, 0);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
int err;
|
|
} raw;
|
|
|
|
raw.magic = SFCI_MAGIC;
|
|
raw.cmd_id = cmd_id;
|
|
raw.err = err;
|
|
|
|
rc = _sfdnsresDispatchCommand(&r, &c, &raw, sizeof(raw));
|
|
if(R_FAILED(rc)) return rc;
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 result;
|
|
} *resp = r.Raw;
|
|
|
|
rc = resp->result;
|
|
return rc;
|
|
}
|
|
|
|
Result sfdnsresGetHostByName(SfdnsresRequestResults *ret, const SfdnsresConfig *config, void *out_he_serialized, const char *name) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
ipcAddSendBuffer(&c, name, strlen(name) + 1, 0);
|
|
|
|
ipcAddRecvBuffer(&c, out_he_serialized, config->serialized_out_hostent_max_size, 0);
|
|
|
|
return _sfdnsresDnsRequestCommand(&c, 2, ret, config, true, NULL);
|
|
}
|
|
|
|
Result sfdnsresGetHostByAddr(SfdnsresRequestResults *ret, const SfdnsresConfig *config, void *out_he_serialized, const void *addr, socklen_t len, int type) {
|
|
IpcCommand c;
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
socklen_t len; // wtf nintendo
|
|
int type;
|
|
int timeout;
|
|
u64 pid_placeholder;
|
|
} raw;
|
|
|
|
ipcInitialize(&c);
|
|
ipcAddSendBuffer(&c, addr, len, 0);
|
|
ipcAddRecvBuffer(&c, out_he_serialized, config->serialized_out_hostent_max_size, 0);
|
|
|
|
raw.magic = SFCI_MAGIC;
|
|
raw.cmd_id = 3;
|
|
raw.len = len;
|
|
raw.type = type;
|
|
raw.timeout = config->timeout;
|
|
raw.pid_placeholder = 0;
|
|
|
|
return _sfdnsresDispatchDnsRequest(&c, ret, &raw, sizeof(raw), true);
|
|
}
|
|
|
|
Result sfdnsresGetHostStringError(int err, char *str, size_t str_size) {
|
|
return _sfdnsresErrorStringGetterCommand(4, err, str, str_size);
|
|
}
|
|
|
|
Result sfdnsresGetGaiStringError(int err, char *str, size_t str_size) {
|
|
return _sfdnsresErrorStringGetterCommand(5, err, str, str_size);
|
|
}
|
|
|
|
Result sfdnsresGetAddrInfo(SfdnsresRequestResults *ret, const SfdnsresConfig *config, const char *node, const char *service,
|
|
const void *hints_serialized, size_t hints_serialized_size, void *res_serialized) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
ipcAddSendBuffer(&c, node, strlen(node) + 1, 0);
|
|
ipcAddSendBuffer(&c, node, strlen(service) + 1, 0);
|
|
ipcAddSendBuffer(&c, hints_serialized, hints_serialized_size, 0);
|
|
|
|
ipcAddRecvBuffer(&c, res_serialized, config->serialized_out_hostent_max_size, 0);
|
|
|
|
return _sfdnsresDnsRequestCommand(&c, 6, ret, config, true, NULL);
|
|
}
|
|
|
|
Result sfdnsresGetNameInfo(SfdnsresRequestResults *ret, const SfdnsresConfig *config,
|
|
const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen,
|
|
char *serv, size_t servlen, int flags) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
ipcAddSendBuffer(&c, sa, salen, 0);
|
|
|
|
ipcAddRecvBuffer(&c, host, hostlen, 0);
|
|
ipcAddRecvBuffer(&c, serv, servlen, 0);
|
|
|
|
return _sfdnsresDnsRequestCommand(&c, 7, ret, config, false, &flags);
|
|
}
|
|
|
|
Result sfdnsresRequestCancelHandle(u32 *out_handle) {
|
|
Result rc;
|
|
IpcCommand c;
|
|
IpcParsedCommand r;
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
u64 pid_placeholder;
|
|
} raw;
|
|
|
|
ipcInitialize(&c);
|
|
ipcSendPid(&c);
|
|
|
|
raw.magic = SFCI_MAGIC;
|
|
raw.cmd_id = 8;
|
|
raw.pid_placeholder = 0;
|
|
|
|
rc = _sfdnsresDispatchCommand(&r, &c, &raw, sizeof(raw));
|
|
if(R_FAILED(rc)) return rc;
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 result;
|
|
u32 handle;
|
|
} *resp = r.Raw;
|
|
|
|
rc = resp->result;
|
|
if(R_FAILED(rc)) return rc;
|
|
|
|
*out_handle = resp->handle;
|
|
|
|
return rc;
|
|
}
|
|
|
|
/// Bug: always sets errno ?
|
|
Result sfdnsresCancelSocketCall(SfdnsresRequestResults *ret, u32 handle) {
|
|
IpcCommand c;
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
u32 handle;
|
|
u64 pid_placeholder;
|
|
} raw;
|
|
|
|
ipcInitialize(&c);
|
|
|
|
raw.magic = SFCI_MAGIC;
|
|
raw.cmd_id = 9;
|
|
raw.handle = handle;
|
|
raw.pid_placeholder = 0;
|
|
|
|
return _sfdnsresDispatchDnsRequest(&c, ret, &raw, sizeof(raw), false);
|
|
}
|
|
|
|
/// Bug: always sets errno ?
|
|
Result sfdnsresCancelAllSocketCalls(SfdnsresRequestResults *ret) {
|
|
IpcCommand c;
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
u64 pid_placeholder;
|
|
} raw;
|
|
|
|
ipcInitialize(&c);
|
|
|
|
raw.magic = SFCI_MAGIC;
|
|
raw.cmd_id = 10;
|
|
raw.pid_placeholder = 0;
|
|
|
|
return _sfdnsresDispatchDnsRequest(&c, ret, &raw, sizeof(raw), false);
|
|
}
|
|
|
|
Result sfdnsresClearDnsIpServerAddressArray(void) {
|
|
Result rc;
|
|
IpcCommand c;
|
|
IpcParsedCommand r;
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
} raw;
|
|
|
|
ipcInitialize(&c);
|
|
|
|
raw.magic = SFCI_MAGIC;
|
|
raw.cmd_id = 11;
|
|
|
|
rc = _sfdnsresDispatchCommand(&r, &c, &raw, sizeof(raw));
|
|
if(R_FAILED(rc)) return rc;
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 result;
|
|
} *resp = r.Raw;
|
|
|
|
rc = resp->result;
|
|
return rc;
|
|
}
|