sfdnsres: Major rewrite using new-ipc, fixed numerous IPC bugs, removed phantom commands

This commit is contained in:
fincs 2019-10-27 17:25:53 +01:00
parent b6af00d908
commit 1592b2892f
No known key found for this signature in database
GPG Key ID: 62C7609ADA219C60
3 changed files with 260 additions and 290 deletions

View File

@ -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 <sys/socket.h> // 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);

View File

@ -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:

View File

@ -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 <string.h>
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);
}