#include "types.h" #include "result.h" #include "ipc.h" #include "services/sm.h" #include "services/sfdnsres.h" #include 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, name == NULL ? 0 : 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, addr == NULL ? 0 : 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; size_t node_size = node == NULL ? 0 : strlen(node) + 1; size_t service_size = service == NULL ? 0 : strlen(service) + 1; hints_serialized_size = hints_serialized == NULL ? 0 : hints_serialized_size; ipcInitialize(&c); ipcAddSendBuffer(&c, node, node_size, 0); ipcAddSendBuffer(&c, service, service_size, 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; salen = sa == NULL ? 0 : salen; hostlen = host == NULL ? 0 : hostlen; servlen = serv == NULL ? 0 : servlen; 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; }