diff --git a/nx/include/switch/services/sfdnsres.h b/nx/include/switch/services/sfdnsres.h index 26ca14de..b23ceba2 100644 --- a/nx/include/switch/services/sfdnsres.h +++ b/nx/include/switch/services/sfdnsres.h @@ -2,47 +2,19 @@ * @file sfdnsres.h * @brief Domain name resolution service IPC wrapper. Please use socket.c instead. * @author TuxSH + * @author fincs * @copyright libnx Authors */ #pragma once #include "../types.h" -#include // For socklen_t, etc. +// SetDnsAddressesPrivateRequest & GetDnsAddressPrivateRequest are stubbed -/// Configuration structure for sfdnsres. -typedef struct { - size_t serialized_out_addrinfos_max_size; ///< For getaddrinfo. - size_t serialized_out_hostent_max_size; ///< For gethostbyname/gethostbyaddr. - bool bypass_nsd; ///< For name gethostbyname/getaddrinfo: bypass the Name Server Daemon. - int timeout; ///< For DNS requests: timeout or 0. -} SfdnsresConfig; - -/// Result values returned by the DNS request commands. -typedef struct { - int ret; ///< Return value (error code). - int errno_; ///< Errno. - ssize_t out_serialized_size; ///< Size of the serialized output buffer or -1 (?). -} SfdnsresRequestResults; - -// SetDnsAddressesPrivate & GetDnsAddressPrivate are stubbed - -Result sfdnsresGetHostByName(SfdnsresRequestResults *ret, const SfdnsresConfig *config, void *out_he_serialized, const char *name); -Result sfdnsresGetHostByAddr(SfdnsresRequestResults *ret, const SfdnsresConfig *config, void *out_he_serialized, const void *addr, socklen_t len, int type); - -Result sfdnsresGetHostStringError(int err, char *str, size_t str_size); -Result sfdnsresGetGaiStringError(int err, char *str, size_t 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); -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); - -/// Requests an handle for use with @ref sfdnsresCancelSocketCall. -Result sfdnsresRequestCancelHandle(u32 *out_handle); -/// Cancels a DNS request (how? which requests?). Bug: always sets errno? -Result sfdnsresCancelSocketCall(SfdnsresRequestResults *ret, u32 handle); -/// Cancels all DNS requests made by the current process (how? which requests?). Bug: always sets errno? -Result sfdnsresCancelAllSocketCalls(SfdnsresRequestResults *ret); -/// Clears up to 4 DNS server IPs registered by bsdcfg (DHCP client, etc.). -Result sfdnsresClearDnsIpServerAddressArray(void); +Result sfdnsresGetHostByNameRequest(u32 timeout, bool use_nsd, const char *name, u32 *ret, u32 *errno_, void *out_buffer, size_t out_buffer_size, u32 *out_serialized_size); +Result sfdnsresGetHostByAddrRequest(const void *in_addr, size_t in_addr_len, u32 type, u32 timeout, u32 *ret, u32 *errno_, void *out_buffer, size_t out_buffer_size, u32 *out_serialized_size); +Result sfdnsresGetHostStringErrorRequest(u32 err, char *out_str, size_t out_str_size); +Result sfdnsresGetGaiStringErrorRequest(u32 err, char *out_str, size_t out_str_size); +Result sfdnsresGetAddrInfoRequest(u32 timeout, bool use_nsd, const char *node, const char *service, const void *in_hints, size_t in_hints_size, void *out_buffer, size_t out_buffer_size, u32 *errno_, s32 *gaie, u32 *out_serialized_size); +Result sfdnsresGetNameInfoRequest(u32 flags, const void *in_sa, size_t in_sa_size, char *out_host, size_t out_host_size, char *out_serv, size_t out_serv_len, u32 timeout, u32 *errno_, s32 *gaie); +Result sfdnsresGetCancelHandleRequest(u32 *out_handle); +Result sfdnsresCancelRequest(u32 handle); diff --git a/nx/source/runtime/devices/socket.c b/nx/source/runtime/devices/socket.c index 37b448e9..6d1da291 100644 --- a/nx/source/runtime/devices/socket.c +++ b/nx/source/runtime/devices/socket.c @@ -25,6 +25,14 @@ #include "services/nifm.h" #include "result.h" +/// Configuration structure for sfdnsres. +typedef struct { + size_t serialized_out_addrinfos_max_size; ///< For getaddrinfo. + size_t serialized_out_hostent_max_size; ///< For gethostbyname/gethostbyaddr. + bool bypass_nsd; ///< For name gethostbyname/getaddrinfo: bypass the Name Server Daemon. + int timeout; ///< For DNS requests: timeout or 0. +} SfdnsresConfig; + __attribute__((weak)) size_t __nx_pollfd_sb_max_fds = 64; int _convert_errno(int bsdErrno); @@ -1425,14 +1433,22 @@ struct hostent *gethostbyname(const char *name) { Result rc = 0; void *out_he_serialized = malloc(g_sfdnsresConfig.serialized_out_hostent_max_size); struct hostent *he = NULL; - SfdnsresRequestResults ret; + u32 ret = 0; + u32 errno_ = 0; if(out_he_serialized == NULL) { h_errno = NO_RECOVERY; errno = ENOMEM; // POSIX leaves this unspecified goto cleanup; } - rc = sfdnsresGetHostByName(&ret, &g_sfdnsresConfig, out_he_serialized, name); + rc = sfdnsresGetHostByNameRequest( + g_sfdnsresConfig.timeout, + !g_sfdnsresConfig.bypass_nsd, + name, + &ret, + &errno_, + out_he_serialized, g_sfdnsresConfig.serialized_out_hostent_max_size, + NULL); if(rc == 0xD401) { h_errno = NO_RECOVERY; errno = EFAULT; // POSIX leaves this unspecified @@ -1448,9 +1464,9 @@ struct hostent *gethostbyname(const char *name) { errno = EINVAL; // POSIX leaves this unspecified goto cleanup; } - if(ret.ret != NETDB_SUCCESS) { - h_errno = ret.ret; - errno = ret.errno_; // POSIX leaves this unspecified + if(ret != NETDB_SUCCESS) { + h_errno = ret; + errno = errno_; // POSIX leaves this unspecified goto cleanup; } @@ -1469,14 +1485,22 @@ struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) { Result rc = 0; void *out_he_serialized = malloc(g_sfdnsresConfig.serialized_out_hostent_max_size); struct hostent *he = NULL; - SfdnsresRequestResults ret; + u32 ret = 0; + u32 errno_ = 0; if(out_he_serialized == NULL) { h_errno = NO_RECOVERY; errno = ENOMEM; // POSIX leaves this unspecified goto cleanup; } - rc = sfdnsresGetHostByAddr(&ret, &g_sfdnsresConfig, out_he_serialized, addr, len, type); + rc = sfdnsresGetHostByAddrRequest( + addr, len, + type, + g_sfdnsresConfig.timeout, + &ret, + &errno_, + out_he_serialized, g_sfdnsresConfig.serialized_out_hostent_max_size, + NULL); if(rc == 0xD401) { h_errno = NO_RECOVERY; // POSIX leaves this unspecified errno = EFAULT; @@ -1492,9 +1516,9 @@ struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) { errno = EINVAL; // POSIX leaves this unspecified goto cleanup; } - if(ret.ret != NETDB_SUCCESS) { - h_errno = ret.ret; - errno = ret.errno_; // POSIX leaves this unspecified + if(ret != NETDB_SUCCESS) { + h_errno = ret; + errno = errno_; // POSIX leaves this unspecified goto cleanup; } @@ -1511,7 +1535,7 @@ cleanup: const char *hstrerror(int err) { static __thread char buf[0x80]; - Result rc = sfdnsresGetHostStringError(err, buf, 0x80); + Result rc = sfdnsresGetHostStringErrorRequest(err, buf, sizeof(buf)); if(R_FAILED(rc)) // a bit limiting, given the broad range of errors the kernel can give to us... strcpy(buf, "System busy, try again."); g_sfdnsresResult = rc; @@ -1524,7 +1548,7 @@ void herror(const char *str) { const char *gai_strerror(int err) { static __thread char buf[0x80]; - Result rc = sfdnsresGetGaiStringError(err, buf, 0x80); + Result rc = sfdnsresGetGaiStringErrorRequest(err, buf, sizeof(buf)); if(R_FAILED(rc)) strcpy(buf, "System busy, try again."); g_sfdnsresResult = rc; @@ -1532,13 +1556,13 @@ const char *gai_strerror(int err) { } int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { - int gaie = 0; Result rc = 0; size_t hints_sz; struct addrinfo_serialized_hdr *hints_serialized = _socketSerializeAddrInfoList(&hints_sz, hints); struct addrinfo_serialized_hdr *out_serialized = NULL; struct addrinfo *out = NULL; - SfdnsresRequestResults ret; + u32 errno_ = 0; + s32 gaie = 0; if(hints_serialized == NULL) { gaie = EAI_MEMORY; @@ -1552,7 +1576,16 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi goto cleanup; } - rc = sfdnsresGetAddrInfo(&ret, &g_sfdnsresConfig, node, service, hints_serialized, hints_sz, out_serialized); + rc = sfdnsresGetAddrInfoRequest( + g_sfdnsresConfig.timeout, + !g_sfdnsresConfig.bypass_nsd, + node, + service, + hints_serialized, hints_sz, + out_serialized, g_sfdnsresConfig.serialized_out_addrinfos_max_size, + &errno_, + &gaie, + NULL); if(rc == 0xD401) { gaie = EAI_SYSTEM; @@ -1568,10 +1601,9 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi goto cleanup; } - gaie = ret.ret; if(gaie != 0) { if(gaie == EAI_SYSTEM) - errno = ret.errno_; + errno = errno_; goto cleanup; } @@ -1591,11 +1623,18 @@ int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags) { - int gaie = 0; Result rc = 0; - SfdnsresRequestResults ret; + u32 errno_ = 0; + s32 gaie = 0; - rc = sfdnsresGetNameInfo(&ret, &g_sfdnsresConfig, sa, salen, host, hostlen, serv, servlen, flags); + rc = sfdnsresGetNameInfoRequest( + flags, + sa, salen, + host, hostlen, + serv, servlen, + g_sfdnsresConfig.timeout, + &errno_, + &gaie); if(rc == 0xD401) { gaie = EAI_SYSTEM; errno = EFAULT; @@ -1610,11 +1649,9 @@ int getnameinfo(const struct sockaddr *sa, socklen_t salen, goto cleanup; } - - gaie = ret.ret; if(gaie != 0) { if(gaie == EAI_SYSTEM) - errno = ret.errno_; + errno = errno_; } cleanup: diff --git a/nx/source/services/sfdnsres.c b/nx/source/services/sfdnsres.c index f66e5fa9..b27531fc 100644 --- a/nx/source/services/sfdnsres.c +++ b/nx/source/services/sfdnsres.c @@ -1,274 +1,235 @@ +#define NX_SERVICE_ASSUME_NON_DOMAIN #include "types.h" #include "result.h" -#include "kernel/ipc.h" +#include "sf/service.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; +NX_INLINE Result _sfdnsresDispatchImpl( + u32 request_id, + const void* in_data, u32 in_data_size, + void* out_data, u32 out_data_size, + const SfDispatchParams disp +) { + Handle h = INVALID_HANDLE; + Result rc = smGetServiceOriginal(&h, smEncodeName("sfdnsres")); + if (R_FAILED(rc)) + return rc; - Result rc = smGetService(&sfdnsres, "sfdnsres"); - if(R_FAILED(rc)) goto cleanup; + // Construct service struct + Service srv = { + .session = h, + .own_handle = 1, + .object_id = 0, + .pointer_buffer_size = 0, // No sfdnsres commands use HipcAutoSelect so this is left as 0 + }; - memcpy(ipcPrepareHeader(c, raw_size), raw, raw_size); + void* in = serviceMakeRequest(&srv, request_id, disp.context, + in_data_size, disp.in_send_pid, + disp.buffer_attrs, disp.buffers, + disp.in_num_objects, disp.in_objects, + disp.in_num_handles, disp.in_handles); - rc = serviceIpcDispatch(&sfdnsres); - if(R_FAILED(rc)) goto cleanup; + if (in_data_size) + __builtin_memcpy(in, in_data, in_data_size); - ipcParse(r); + rc = svcSendSyncRequest(h); + if (R_SUCCEEDED(rc)) { + void* out = NULL; + rc = serviceParseResponse(&srv, + out_data_size, &out, + disp.out_num_objects, disp.out_objects, + disp.out_handle_attrs, disp.out_handles); -cleanup: - serviceClose(&sfdnsres); + if (R_SUCCEEDED(rc) && out_data && out_data_size) + __builtin_memcpy(out_data, out, out_data_size); + } + + serviceClose(&srv); 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); +#define _sfdnsresDispatch(_rid,...) \ + _sfdnsresDispatchImpl((_rid),NULL,0,NULL,0,(SfDispatchParams){ __VA_ARGS__ }) - rc = _sfdnsresDispatchCommand(&r, c, raw, raw_size); - if(R_FAILED(rc)) return rc; +#define _sfdnsresDispatchIn(_rid,_in,...) \ + _sfdnsresDispatchImpl((_rid),&(_in),sizeof(_in),NULL,0,(SfDispatchParams){ __VA_ARGS__ }) + +#define _sfdnsresDispatchOut(_rid,_out,...) \ + _sfdnsresDispatchImpl((_rid),NULL,0,&(_out),sizeof(_out),(SfDispatchParams){ __VA_ARGS__ }) + +#define _sfdnsresDispatchInOut(_rid,_in,_out,...) \ + _sfdnsresDispatchImpl((_rid),&(_in),sizeof(_in),&(_out),sizeof(_out),(SfDispatchParams){ __VA_ARGS__ }) + +static Result _sfdnsresCmdInErrOutStr(u32 err, char *out_str, size_t out_str_size, u32 cmd_id) { + return _sfdnsresDispatchIn(cmd_id, err, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out_str, out_str_size } }, + ); +} + +Result sfdnsresGetHostByNameRequest(u32 timeout, bool use_nsd, const char *name, u32 *ret, u32 *errno_, void *out_buffer, size_t out_buffer_size, u32 *out_serialized_size) { + const struct { + u32 use_nsd; // actually u8 bool, but promoted to u32 for convenience + u32 timeout; + u64 pid_placeholder; + } in = { use_nsd ? 1 : 0, timeout, 0 }; struct { - u64 magic; - u64 result; - int ret; - int errno_; - int out_serialized_size; // OOB if !has_serialized_data - } *resp = r.Raw; + u32 ret; + u32 errno_; + u32 serialized_size; + } out = {}; - rc = resp->result; - if(R_FAILED(rc)) return rc; + Result rc = _sfdnsresDispatchInOut(2, in, out, + .in_send_pid = true, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + }, + .buffers = { + { name, name ? strlen(name) + 1 : 0 }, + { out_buffer, out_buffer_size }, + }, + ); - ret->ret = resp->ret; - ret->errno_ = resp->errno_; - ret->out_serialized_size = has_serialized_data_out ? resp->out_serialized_size : 0; + if (R_SUCCEEDED(rc)) { + if (ret) *ret = out.ret; + if (errno_) *errno_ = out.errno_; + if (out_serialized_size) *out_serialized_size = out.serialized_size; + } 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; +Result sfdnsresGetHostByAddrRequest(const void *in_addr, size_t in_addr_len, u32 type, u32 timeout, u32 *ret, u32 *errno_, void *out_buffer, size_t out_buffer_size, u32 *out_serialized_size) { + const struct { + u32 len; // wtf nintendo + u32 type; + u32 timeout; + u32 _padding; 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); + } in = { (u32)in_addr_len, type, timeout, 0, 0 }; struct { - u64 magic; - u64 cmd_id; - int err; - } raw; + u32 ret; + u32 errno_; + u32 serialized_size; + } out = {}; - raw.magic = SFCI_MAGIC; - raw.cmd_id = cmd_id; - raw.err = err; + Result rc = _sfdnsresDispatchInOut(3, in, out, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + }, + .buffers = { + { in_addr, in_addr_len }, + { out_buffer, out_buffer_size }, + }, + ); - rc = _sfdnsresDispatchCommand(&r, &c, &raw, sizeof(raw)); - if(R_FAILED(rc)) return rc; + if (R_SUCCEEDED(rc)) { + if (ret) *ret = out.ret; + if (errno_) *errno_ = out.errno_; + if (out_serialized_size) *out_serialized_size = out.serialized_size; + } - 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 sfdnsresGetHostStringErrorRequest(u32 err, char *out_str, size_t out_str_size) { + return _sfdnsresCmdInErrOutStr(err, out_str, out_str_size, 4); } -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; +Result sfdnsresGetGaiStringErrorRequest(u32 err, char *out_str, size_t out_str_size) { + return _sfdnsresCmdInErrOutStr(err, out_str, out_str_size, 5); +} + +Result sfdnsresGetAddrInfoRequest(u32 timeout, bool use_nsd, const char *node, const char *service, const void *in_hints, size_t in_hints_size, void *out_buffer, size_t out_buffer_size, u32 *errno_, s32 *gaie, u32 *out_serialized_size) { + const struct { + u32 use_nsd; // actually u8 bool, but promoted to u32 for convenience + u32 timeout; u64 pid_placeholder; - } raw; + } in = { use_nsd ? 1 : 0, timeout, 0 }; - 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; + u32 errno_; + s32 gaie; + u32 serialized_size; + } out = {}; + + Result rc = _sfdnsresDispatchInOut(6, in, out, + .in_send_pid = true, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + }, + .buffers = { + { node, node ? strlen(node) + 1 : 0 }, + { service, service ? strlen(service) + 1 : 0 }, + { in_hints, in_hints_size }, + { out_buffer, out_buffer_size }, + }, + ); + + if (R_SUCCEEDED(rc)) { + if (errno_) *errno_ = out.errno_; + if (gaie) *gaie = out.gaie; + if (out_serialized_size) *out_serialized_size = out.serialized_size; + } + + return rc; +} + +Result sfdnsresGetNameInfoRequest(u32 flags, const void *in_sa, size_t in_sa_size, char *out_host, size_t out_host_size, char *out_serv, size_t out_serv_len, u32 timeout, u32 *errno_, s32 *gaie) { + const struct { + u32 flags; + u32 timeout; 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; + } in = { flags, timeout, 0 }; 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 errno_; + s32 gaie; + } out; + + Result rc = _sfdnsresDispatchInOut(7, in, out, + .in_send_pid = true, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + }, + .buffers = { + { in_sa, in_sa_size }, + { out_host, out_host_size }, + { out_serv, out_serv_len }, + }, + ); + + if (R_SUCCEEDED(rc)) { + if (errno_) *errno_ = out.errno_; + if (gaie) *gaie = out.gaie; + } + + return rc; +} + +Result sfdnsresGetCancelHandleRequest(u32 *out_handle) { + u64 pid_placeholder = 0; + return _sfdnsresDispatchInOut(8, pid_placeholder, *out_handle, .in_send_pid = true); +} + +Result sfdnsresCancelRequest(u32 handle) { + const struct { u32 handle; + u32 _padding; u64 pid_placeholder; - } raw; + } in = { handle, 0, 0 }; - 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; + return _sfdnsresDispatchIn(9, in, .in_send_pid = true); }