libnx/nx/source/services/sfdnsres.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;
}